From 1675fc7caf759b7ae0d43cb87b7c444af4896b89 Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Thu, 30 Jun 2016 21:42:40 -0400 Subject: [PATCH] Add %HTML.TargetNoreferrer, which adds rel="noreferrer" when target attribute is set Signed-off-by: Edward Z. Yang --- NEWS | 5 +++ configdoc/usage.xml | 5 +++ library/HTMLPurifier.includes.php | 2 + library/HTMLPurifier.safe-includes.php | 2 + .../AttrTransform/TargetNoreferrer.php | 37 +++++++++++++++ library/HTMLPurifier/ConfigSchema/schema.ser | Bin 15426 -> 15525 bytes .../schema/HTML.TargetNoreferrer.txt | 9 ++++ .../HTMLModule/TargetNoreferrer.php | 21 +++++++++ library/HTMLPurifier/HTMLModuleManager.php | 5 +++ .../HTMLModule/TargetBlankTest.php | 2 +- .../HTMLModule/TargetNoreferrerTest.php | 42 ++++++++++++++++++ .../Strategy/ValidateAttributesTest.php | 2 +- 12 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 library/HTMLPurifier/AttrTransform/TargetNoreferrer.php create mode 100644 library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt create mode 100644 library/HTMLPurifier/HTMLModule/TargetNoreferrer.php create mode 100644 tests/HTMLPurifier/HTMLModule/TargetNoreferrerTest.php diff --git a/NEWS b/NEWS index a098fb46..576365ed 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,11 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier ========================== 4.8.0, unknown release date +# By default, when a link has a target attribute associated + with it, we now also add rel="noreferrer" in order to + prevent the new window from being able to overwrite + the original frame. To disable this protection, + set %HTML.TargetNoreferrer to FALSE. ! Full PHP 7 compatibility, the test suite is ALL GO. ! %CSS.AllowDuplicates permits duplicate CSS properties. ! Support for 'tel' URIs. diff --git a/configdoc/usage.xml b/configdoc/usage.xml index afdea088..d3856974 100644 --- a/configdoc/usage.xml +++ b/configdoc/usage.xml @@ -227,6 +227,11 @@ 271 + + + 276 + + 27 diff --git a/library/HTMLPurifier.includes.php b/library/HTMLPurifier.includes.php index bc28112c..d2329fd8 100644 --- a/library/HTMLPurifier.includes.php +++ b/library/HTMLPurifier.includes.php @@ -137,6 +137,7 @@ require 'HTMLPurifier/AttrTransform/SafeObject.php'; require 'HTMLPurifier/AttrTransform/SafeParam.php'; require 'HTMLPurifier/AttrTransform/ScriptRequired.php'; require 'HTMLPurifier/AttrTransform/TargetBlank.php'; +require 'HTMLPurifier/AttrTransform/TargetNoreferrer.php'; require 'HTMLPurifier/AttrTransform/Textarea.php'; require 'HTMLPurifier/ChildDef/Chameleon.php'; require 'HTMLPurifier/ChildDef/Custom.php'; @@ -175,6 +176,7 @@ require 'HTMLPurifier/HTMLModule/StyleAttribute.php'; require 'HTMLPurifier/HTMLModule/Tables.php'; require 'HTMLPurifier/HTMLModule/Target.php'; require 'HTMLPurifier/HTMLModule/TargetBlank.php'; +require 'HTMLPurifier/HTMLModule/TargetNoreferrer.php'; require 'HTMLPurifier/HTMLModule/Text.php'; require 'HTMLPurifier/HTMLModule/Tidy.php'; require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php'; diff --git a/library/HTMLPurifier.safe-includes.php b/library/HTMLPurifier.safe-includes.php index c58a9403..fe587c78 100644 --- a/library/HTMLPurifier.safe-includes.php +++ b/library/HTMLPurifier.safe-includes.php @@ -131,6 +131,7 @@ require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/TargetBlank.php'; +require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoreferrer.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/Textarea.php'; require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php'; require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php'; @@ -169,6 +170,7 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/TargetBlank.php'; +require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoreferrer.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php'; diff --git a/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php b/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php new file mode 100644 index 00000000..587dc2e0 --- /dev/null +++ b/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php @@ -0,0 +1,37 @@ +W diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt b/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt new file mode 100644 index 00000000..cb5a0b0e --- /dev/null +++ b/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt @@ -0,0 +1,9 @@ +HTML.TargetNoreferrer +TYPE: bool +VERSION: 4.8.0 +DEFAULT: TRUE +--DESCRIPTION-- +If enabled, noreferrer rel attributes are added to links which have +a target attribute associated with them. This prevents malicious +destinations from overwriting the original window. +--# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php b/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php new file mode 100644 index 00000000..32484d60 --- /dev/null +++ b/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php @@ -0,0 +1,21 @@ +addBlankElement('a'); + $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetNoreferrer(); + } +} diff --git a/library/HTMLPurifier/HTMLModuleManager.php b/library/HTMLPurifier/HTMLModuleManager.php index f3a17cb0..2546c043 100644 --- a/library/HTMLPurifier/HTMLModuleManager.php +++ b/library/HTMLPurifier/HTMLModuleManager.php @@ -271,6 +271,11 @@ class HTMLPurifier_HTMLModuleManager if ($config->get('HTML.TargetBlank')) { $modules[] = 'TargetBlank'; } + // NB: HTML.TargetNoreferrer must be AFTER HTML.TargetBlank + // so that its post-attr-transform gets run afterwards. + if ($config->get('HTML.TargetNoreferrer')) { + $modules[] = 'TargetNoreferrer'; + } // merge in custom modules $modules = array_merge($modules, $this->userModules); diff --git a/tests/HTMLPurifier/HTMLModule/TargetBlankTest.php b/tests/HTMLPurifier/HTMLModule/TargetBlankTest.php index c73aea92..dbb755f6 100644 --- a/tests/HTMLPurifier/HTMLModule/TargetBlankTest.php +++ b/tests/HTMLPurifier/HTMLModule/TargetBlankTest.php @@ -13,7 +13,7 @@ class HTMLPurifier_HTMLModule_TargetBlankTest extends HTMLPurifier_HTMLModuleHar { $this->assertResult( 'abc', - 'abc' + 'abc' ); } diff --git a/tests/HTMLPurifier/HTMLModule/TargetNoreferrerTest.php b/tests/HTMLPurifier/HTMLModule/TargetNoreferrerTest.php new file mode 100644 index 00000000..52dbb4a1 --- /dev/null +++ b/tests/HTMLPurifier/HTMLModule/TargetNoreferrerTest.php @@ -0,0 +1,42 @@ +config->set('HTML.TargetNoreferrer', true); + $this->config->set('Attr.AllowedFrameTargets', '_blank'); + } + + public function testNoreferrer() + { + $this->assertResult( + 'x', + 'x' + ); + } + + public function testNoreferrerNoDupe() + { + $this->config->set('Attr.AllowedRel', 'noreferrer'); + $this->assertResult( + 'x', + 'x' + ); + } + + public function testTargetBlankNoreferrer() + { + $this->config->set('HTML.TargetBlank', true); + $this->assertResult( + 'x', + 'x' + ); + } + + +} + +// vim: et sw=4 sts=4 diff --git a/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php b/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php index 2bf71793..19fca6ac 100644 --- a/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php +++ b/tests/HTMLPurifier/Strategy/ValidateAttributesTest.php @@ -189,7 +189,7 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends { $this->config->set('Attr.AllowedFrameTargets', '_top'); $this->config->set('HTML.Doctype', 'XHTML 1.0 Transitional'); - $this->assertResult(''); + $this->assertResult(''); } public function testRemoveTargetWhenNotSupported()