[Pkg-javascript-commits] [dompurify.js] 01/03: Imported Upstream version 0.7.4~dfsg1

Alexandre Viau aviau at moszumanska.debian.org
Wed May 18 16:14:21 UTC 2016


This is an automated email from the git hooks/post-receive script.

aviau pushed a commit to branch master
in repository dompurify.js.

commit a2d553699f408201092004c587f559854aa591fd
Author: aviau <alexandre at alexandreviau.net>
Date:   Wed May 18 12:08:53 2016 -0400

    Imported Upstream version 0.7.4~dfsg1
---
 README.md               |   4 +-
 bower.json              |   2 +-
 package.json            |   2 +-
 src/purify.js           | 106 +++++++++++++++++++++++----------------
 test/fixtures/expect.js | 131 ++++++++++++++++++++++++++----------------------
 test/test-suite.js      |   1 +
 website/index.html      |   4 +-
 7 files changed, 141 insertions(+), 109 deletions(-)

diff --git a/README.md b/README.md
index 1f96897..0e21e5c 100644
--- a/README.md
+++ b/README.md
@@ -183,8 +183,8 @@ We recently implemented a Hook-API allowing developers to create their own DOMPu
 
 ## Who contributed?
 
-Several people need to be listed here! [@garethheyes](https://twitter.com/garethheyes) for invaluable help, [@shafigullin](https://twitter.com/shafigullin) for breaking the library multiple times and thereby strengthening it, [@mmrupp](https://twitter.com/mmrupp) and [@irsdl](https://twitter.com/irsdl) for doing the same.
+Several people need to be listed here! [@garethheyes](https://twitter.com/garethheyes) and [@filedescriptor](https://twitter.com/filedescriptor) for invaluable help, [@shafigullin](https://twitter.com/shafigullin) for breaking the library multiple times and thereby strengthening it, [@mmrupp](https://twitter.com/mmrupp) and [@irsdl](https://twitter.com/irsdl) for doing the same.
 
-Big thanks also go to [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro) and [@fhemberger](https://twitter.com/fhemberger)! Further, thanks [@neilj](https://twitter.com/neilj) for his code review and countless small optimizations, fixes and beautifications. Big thanks also go to [@tdeekens](https://twitter.com/tdeekens) f [...]
+Big thanks also go to [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro) and [@fhemberger](https://twitter.com/fhemberger)! Further, thanks [@neilj](https://twitter.com/neilj) and [@0xsobky](https://twitter.com/0xsobky) for their code reviews and countless small optimizations, fixes and beautifications. Big thanks also go [...]
 
 And last but not least, thanks to [BrowserStack](https://browserstack.com) for supporting this project with their services for free and delivering excellent, dedicated and very professional support on top of that.
diff --git a/bower.json b/bower.json
index ef68422..a08c55a 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "DOMPurify",
-  "version": "0.7.3",
+  "version": "0.7.4",
   "homepage": "https://github.com/cure53/DOMPurify",
   "author": "Cure53 <info at cure53.de>",
   "description": "A DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG",
diff --git a/package.json b/package.json
index 61bb57e..2af2207 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
   },
   "name": "dompurify",
   "description": "DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. It's written in JavaScript and works in all modern browsers (Safari, Opera (15+), Internet Explorer (10+), Firefox and Chrome - as well as almost anything else using Blink or WebKit). DOMPurify is written by security people who have vast background in web attacks and XSS. Fear not.",
-  "version": "0.7.3",
+  "version": "0.7.4",
   "main": "src/purify.js",
   "directories": {
     "test": "test"
diff --git a/src/purify.js b/src/purify.js
index e705be8..71f62b7 100644
--- a/src/purify.js
+++ b/src/purify.js
@@ -21,7 +21,7 @@
      * Version label, exposed for easier checks
      * if DOMPurify is up to date or not
      */
-    DOMPurify.version = '0.7.3';
+    DOMPurify.version = '0.7.4';
 
     if (!window || !window.document || window.document.nodeType !== 9) {
         // not running in a browser, provide a factory function
@@ -211,6 +211,10 @@
      */
     var SAFE_FOR_TEMPLATES = false;
 
+    /* Specify template detection regex for SAFE_FOR_TEMPLATES mode */
+    var MUSTACHE_EXPR = /\{\{[\s\S]*|[\s\S]*\}\}/gm;
+    var ERB_EXPR = /<%[\s\S]*|[\s\S]*%>/gm;
+
     /* Decide if document with <html>... should be returned */
     var WHOLE_DOCUMENT = false;
 
@@ -239,6 +243,17 @@
         'audio', 'head', 'math', 'script', 'style', 'svg', 'video'
     ]);
 
+    /* Tags that are safe for data: URIs */
+    var DATA_URI_TAGS = _addToSet({}, [
+        'audio', 'video', 'img', 'source'
+    ]);
+
+    /* Attributes safe for values like "javascript:" */
+    var URI_SAFE_ATTRIBUTES = _addToSet({}, [
+        'alt','class','for','id','label','name','pattern','placeholder',
+        'summary','title','value','style','xmlns'
+    ]);
+
     /* Keep a reference to config to pass to hooks */
     var CONFIG = null;
 
@@ -277,6 +292,10 @@
         SANITIZE_DOM        = cfg.SANITIZE_DOM        !== false; // Default true
         KEEP_CONTENT        = cfg.KEEP_CONTENT        !== false; // Default true
 
+        if (SAFE_FOR_TEMPLATES) {
+            ALLOW_DATA_ATTR = false;
+        }
+
         if (RETURN_DOM_FRAGMENT) {
             RETURN_DOM = true;
         }
@@ -333,7 +352,7 @@
 
         /* Some browsers throw, some browsers return null for the code above
            DOMParser with text/html support is only in very recent browsers. */
-        if (!doc){
+        if (!doc) {
             doc = implementation.createHTMLDocument('');
             body = doc.body;
             body.parentNode.removeChild(body.parentNode.firstElementChild);
@@ -341,13 +360,12 @@
         }
 
         /* Work on whole document or just its body */
-        if (typeof doc.getElementsByTagName === 'function'){
+        if (typeof doc.getElementsByTagName === 'function') {
             return doc.getElementsByTagName(
                 WHOLE_DOCUMENT ? 'html' : 'body')[0];
-        } else {
-            return getElementsByTagName.call(doc,
-                WHOLE_DOCUMENT ? 'html' : 'body')[0];
         }
+        return getElementsByTagName.call(doc,
+            WHOLE_DOCUMENT ? 'html' : 'body')[0];
     };
 
     /**
@@ -389,9 +407,6 @@
         return false;
     };
 
-    var MUSTACHE_EXPR = /\{\{.*|.*\}\}/gm;
-    var ERB_EXPR = /<%.*|.*%>/gm;
-
     /**
      * _sanitizeElements
      *
@@ -403,6 +418,7 @@
      * @return  true if node was killed, false if left alive
      */
     var _sanitizeElements = function(currentNode) {
+        var tagName, content;
         /* Execute a hook if present */
         _executeHook('beforeSanitizeElements', currentNode, null);
 
@@ -413,7 +429,7 @@
         }
 
         /* Now let's check the element's type and name */
-        var tagName = currentNode.nodeName.toLowerCase();
+        tagName = currentNode.nodeName.toLowerCase();
 
         /* Execute a hook if present */
         _executeHook('uponSanitizeElement', currentNode, {
@@ -442,7 +458,7 @@
         /* Sanitize element content to be template-safe */
         if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
             /* Get the element's text content */
-            var content = currentNode.textContent;
+            content = currentNode.textContent;
             content = content.replace(MUSTACHE_EXPR, ' ');
             content = content.replace(ERB_EXPR, ' ');
             currentNode.textContent = content;
@@ -455,7 +471,7 @@
     };
 
     var DATA_ATTR = /^data-[\w.\u00B7-\uFFFF-]/;
-    var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
+    var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
     /* This needs to be extensive thanks to Webkit/Blink's behavior */
     var ATTR_WHITESPACE = /[\x00-\x20\xA0\u1680\u180E\u2000-\u2029\u205f\u3000]/g;
 
@@ -471,21 +487,21 @@
      * @return  void
      */
     var _sanitizeAttributes = function(currentNode) {
+        var attr, name, value, lcName, idAttr, attributes, hookEvent, l;
         /* Execute a hook if present */
         _executeHook('beforeSanitizeAttributes', currentNode, null);
 
-        var attributes = currentNode.attributes;
+        attributes = currentNode.attributes;
 
         /* Check if we have attributes; if not we might have a text node */
         if (!attributes) { return; }
 
-        var hookEvent = {
+        hookEvent = {
             attrName: '',
             attrValue: '',
             keepAttr: true
         };
-        var l = attributes.length;
-        var attr, name, value, lcName, idAttr;
+        l = attributes.length;
 
         /* Go backwards over all attributes; safely remove bad ones */
         while (l--) {
@@ -536,30 +552,32 @@
                 continue;
             }
 
+            /* Sanitize attribute content to be template-safe */
+            if (SAFE_FOR_TEMPLATES) {
+                value = value.replace(MUSTACHE_EXPR, ' ');
+                value = value.replace(ERB_EXPR, ' ');
+            }
+
             if (
                 /* Check the name is permitted */
-                (
-                 (ALLOWED_ATTR[lcName] && !FORBID_ATTR[lcName]) ||
-                 /* Allow potentially valid data-* attributes
-                    * At least one character after "-" (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
-                    * XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804) */
-                 (!SAFE_FOR_TEMPLATES && ALLOW_DATA_ATTR && DATA_ATTR.test(lcName))
-                ) &&
-                /* Get rid of script and data URIs */
-                (
-                 !IS_SCRIPT_OR_DATA.test(value.replace(ATTR_WHITESPACE,'')) ||
-                 /* Keep image data URIs alive if src is allowed */
-                 (lcName === 'src' && value.indexOf('data:') === 0 &&
-                  currentNode.nodeName === 'IMG')
-                )
+                (ALLOWED_ATTR[lcName] && !FORBID_ATTR[lcName] && (
+                  /* Check no script, data or unknown possibly unsafe URI
+                     unless we know URI values are safe for that attribute */
+                  URI_SAFE_ATTRIBUTES[lcName] ||
+                  IS_ALLOWED_URI.test(value.replace(ATTR_WHITESPACE,'')) ||
+                  /* Keep image data URIs alive if src is allowed */
+                  (lcName === 'src' && value.indexOf('data:') === 0 &&
+                   DATA_URI_TAGS[currentNode.nodeName.toLowerCase()])
+                )) ||
+                /* Allow potentially valid data-* attributes:
+                 * At least one character after "-" (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
+                 * XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
+                 * We don't need to check the value; it's always URI safe.
+                 */
+                 (ALLOW_DATA_ATTR && DATA_ATTR.test(lcName))
             ) {
                 /* Handle invalid data-* attribute set by try-catching it */
                 try {
-                    /* Sanitize attribute content to be template-safe */
-                    if (SAFE_FOR_TEMPLATES) {
-                        value = value.replace(MUSTACHE_EXPR, ' ');
-                        value = value.replace(ERB_EXPR, ' ');
-                    }
                     currentNode.setAttribute(name, value);
                 } catch (e) {}
             }
@@ -627,6 +645,7 @@
      * @param {Object} configuration object
      */
     DOMPurify.sanitize = function(dirty, cfg) {
+        var body, currentNode, oldNode, nodeIterator, returnNode;
         /* Make sure we have a string to sanitize.
            DO NOT return early, as this will return the wrong type if
            the user has requested a DOM object rather than a string */
@@ -634,14 +653,18 @@
             dirty = '';
         }
 
-        /* Stringify, in case dirty is an array or other object */
+        /* Stringify, in case dirty is an object */
         if (typeof dirty !== 'string') {
-            dirty = dirty.toString();
+            if (typeof dirty.toString !== 'function') {
+                throw new TypeError('toString is not a function');
+            } else {
+                dirty = dirty.toString();
+            }
         }
 
         /* Check we can run. Otherwise fall back or ignore */
         if (!DOMPurify.isSupported) {
-            if (typeof window.toStaticHTML === 'object' 
+            if (typeof window.toStaticHTML === 'object'
                 || typeof window.toStaticHTML === 'function') {
                 return window.toStaticHTML(dirty);
             }
@@ -657,7 +680,7 @@
         }
 
         /* Initialize the document to work on */
-        var body = _initDocument(dirty);
+        body = _initDocument(dirty);
 
         /* Check we have a DOM node from the data */
         if (!body) {
@@ -665,9 +688,7 @@
         }
 
         /* Get node iterator */
-        var currentNode;
-        var oldNode;
-        var nodeIterator = _createIterator(body);
+        nodeIterator = _createIterator(body);
 
         /* Now start iterating over the created document */
         while ( (currentNode = nodeIterator.nextNode()) ) {
@@ -694,7 +715,6 @@
         }
 
         /* Return sanitized string or DOM */
-        var returnNode;
         if (RETURN_DOM) {
 
             if (RETURN_DOM_FRAGMENT) {
diff --git a/test/fixtures/expect.js b/test/fixtures/expect.js
index 5aec4a5..8faa7bd 100644
--- a/test/fixtures/expect.js
+++ b/test/fixtures/expect.js
@@ -1,11 +1,22 @@
-module.exports = [{
+module.exports = [
+  {
+      "title": "safe usage of URI-like attribute values (see #135)",
+      "payload": "<b href=\"javascript:alert(1)\" title=\"javascript:alert(2)\"></b>",
+      "expected": "<b title=\"javascript:alert(2)\"></b>"
+  },
+     {
+      "title": "src Attributes for IMG, AUDIO, VIDEO and SOURCE (see #131)",
+      "payload": "<img src=\"data:,123\"><audio src=\"data:,456\"></audio><video src=\"data:,789\"></video><source src=\"data:,012\"><div src=\"data:,345\">",
+      "expected": "<img src=\"data:,123\"><audio src=\"data:,456\"></audio><video src=\"data:,789\"></video><source src=\"data:,012\"><div></div>"
+  }, 
+     {
       "title": "DOM Clobbering against document.createElement() (see #47)",
-      "payload": "<img src=x:x name=createElement><img src=y id=createElement>",
-      "expected": "<img src=\"x:x\"><img src=\"y\">"
+      "payload": "<img src=x name=createElement><img src=y id=createElement>",
+      "expected": "<img src=\"x\"><img src=\"y\">"
   }, {
       "title": "DOM Clobbering against an empty cookie",
-      "payload": "<img src=x:x name=cookie>",
-      "expected": "<img src=\"x:x\">"
+      "payload": "<img src=x name=cookie>",
+      "expected": "<img src=\"x\">"
   }, {
       "title": "JavaScript URIs using Unicode LS/PS I",
       "payload": "123<a href='\u2028javascript:alert(1)'>I am a dolphin!</a>",
@@ -40,8 +51,8 @@ module.exports = [{
       "expected": ["", "<form><input><input></form>"]
   }, {
       "title": "DOM clobbering: getElementById",
-      "payload": "<img src=x:x name=getElementById>",
-      "expected": "<img src=\"x:x\">"
+      "payload": "<img src=x name=getElementById>",
+      "expected": "<img src=\"x\">"
   }, {
       "title": "DOM clobbering: location",
       "payload": "<a href=\"#some-code-here\" id=\"location\">invisible",
@@ -88,35 +99,35 @@ module.exports = [{
       "expected": "<p>hello</p>"
   }, {
       "title": "mXSS Variation I",
-      "payload": "<listing><img onerror=\"alert(1);//\" src=x:x><t t></listing>",
+      "payload": "<listing><img onerror=\"alert(1);//\" src=x><t t></listing>",
       "expected": [
-        "<img onerror=\"alert(1);//\" src=x:x>",
-        "<img src=\"x:x\">"
+        "<img onerror=\"alert(1);//\" src=x>",
+        "<img src=\"x\">"
       ]
   }, {
       "title": "mXSS Variation II",
-      "payload": "<img src=x:x id/=' onerror=alert(1)//'>",
-      "expected": ["<img src=\"x:x\">", "<img id=\"\" src=\"x:x\">"]
+      "payload": "<img src=x id/=' onerror=alert(1)//'>",
+      "expected": ["<img src=\"x\">", "<img id=\"\" src=\"x\">"]
   }, {
       "title": "Textarea and comments enabling img element",
       "payload": "<textarea>@shafigullin</textarea><!--</textarea><img src=x onerror=alert(1)>-->",
       "expected": "<textarea>@shafigullin</textarea>"
   }, {
       "title": "Img element inside noscript terminated inside comment",
-      "payload": "<b><noscript><!-- </noscript><img src=x:x onerror=alert(1) --></noscript>",
-      "expected": ["<b></b>", "<b><img src=\"x:x\"></b>"]
+      "payload": "<b><noscript><!-- </noscript><img src=x onerror=alert(1) --></noscript>",
+      "expected": ["<b></b>", "<b><img src=\"x\"></b>"]
   }, {
       "title": "Img element inside noscript terminated inside attribute",
-      "payload": "<b><noscript><a alt=\"</noscript><img src=x:x onerror=alert(1)>\"></noscript>",
+      "payload": "<b><noscript><a alt=\"</noscript><img src=x onerror=alert(1)>\"></noscript>",
       "expected": [
-          "<b><img src=\"x:x\">\"></b>",
-          "<b><a alt=\"</noscript><img src=x:x onerror=alert(1)>\"></a></b>",
-          "<b><a alt=\"</noscript><img src=x:x onerror=alert(1)>\"></a></b>"
+          "<b><img src=\"x\">\"></b>",
+          "<b><a alt=\"</noscript><img src=x onerror=alert(1)>\"></a></b>",
+          "<b><a alt=\"</noscript><img src=x onerror=alert(1)>\"></a></b>"
       ]
   }, {
       "title": "Img element inside shadow DOM template",
-      "payload": "<body><template><s><template><s><img src=x:x onerror=alert(1)>@shafigullin</s></template></s></template>",
-      "expected": "<template><s><template><s><img src=\"x:x\">@shafigullin</s></template></s></template>"
+      "payload": "<body><template><s><template><s><img src=x onerror=alert(1)>@shafigullin</s></template></s></template>",
+      "expected": "<template><s><template><s><img src=\"x\">@shafigullin</s></template></s></template>"
   }, {
       "title": "Low-range-ASCII obfuscated JavaScript URI",
       "payload": "<a href=\"\u0001java\u0003script:alert(1)\">@shafigullin<a>",
@@ -126,8 +137,8 @@ module.exports = [{
       ]
   }, {
       "title": "Img inside style inside broken option element",
-      "payload": "\u0001<option><style></option></select><b><img src=x:x onerror=alert(1)></style></option>",
-      "expected": "\u0001<option><style></option></select><b><img src=x:x onerror=alert(1)></style></option>"
+      "payload": "\u0001<option><style></option></select><b><img src=x onerror=alert(1)></style></option>",
+      "expected": "\u0001<option><style></option></select><b><img src=x onerror=alert(1)></style></option>"
   }, {
       "title": "Iframe inside option element",
       "payload": "<option><iframe></select><b><script>alert(1)</script>",
@@ -141,12 +152,12 @@ module.exports = [{
       "expected": ""
   }, {
       "title": "Image after style to trick jQuery tag-completion",
-      "payload": "<b><style><style/><img src=x:x onerror=alert(1)>",
-      "expected": "<b><style><style/><img src=x:x onerror=alert(1)></style></b>"
+      "payload": "<b><style><style/><img src=x onerror=alert(1)>",
+      "expected": "<b><style><style/><img src=x onerror=alert(1)></style></b>"
   }, {
       "title": "Image after self-closing style to trick jQuery tag-completion",
-      "payload": "<b><style><style////><img src=x:x onerror=alert(1)></style>",
-      "expected": "<b><style><style////><img src=x:x onerror=alert(1)></style></b>"
+      "payload": "<b><style><style////><img src=x onerror=alert(1)></style>",
+      "expected": "<b><style><style////><img src=x onerror=alert(1)></style></b>"
   }, {
       "title": "MathML example",
       "payload": "<math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\">\n  <mrow>\n    <menclose notation=\"box\"><mi>a</mi></menclose><mo>,</mo>\n    <menclose notation=\"box\"><mi mathcolor=\"#FF0000\">a</mi></menclose><mo>,</mo>\n    <menclose notation=\"box\" mathcolor=\"#FF0000\"><mi>a</mi></menclose><mo>,</mo>\n    <menclose notation=\"box\" mathbackground=\"#80FF80\"><mi mathcolor=\"#FF0000\">a</mi></menclose><mo>,</mo>\n    <menclose notation=\"box\" mathcolor=\"# [...]
@@ -180,10 +191,10 @@ module.exports = [{
       ]
   }, {
       "title": "DOM clobbering attack using name=body and injecting SVG + keygen",
-      "payload": "<image name=body><img src=x:x><svg onload=alert(1); autofocus>, <keygen onfocus=alert(1); autofocus>",
+      "payload": "<image name=body><img src=x><svg onload=alert(1); autofocus>, <keygen onfocus=alert(1); autofocus>",
       "expected": [
-          "<img><img src=\"x:x\"><svg>, </svg>",
-          "<img><img src=\"x:x\"><svg xmlns=\"http://www.w3.org/2000/svg\">, </svg></svg>"
+          "<img><img src=\"x\"><svg>, </svg>",
+          "<img><img src=\"x\"><svg xmlns=\"http://www.w3.org/2000/svg\">, </svg></svg>"
       ]
   }, {
       "title": "Bypass using multiple unknown attributes",
@@ -314,7 +325,7 @@ module.exports = [{
           "<div id=\"23\"><form><input><button>X</button>//[\"'`-->]]>]</form></div>"
       ]
   }, {
-      "payload": "<div id=\"24\">1<set/xmlns=`urn:schemas-microsoft-com:time` style=`behAvior:url(#default#time2)` attributename=`innerhtml` to=`<img/src=\"x:x\"onerror=alert(24)>`>//[\"'`-->]]>]</div>",
+      "payload": "<div id=\"24\">1<set/xmlns=`urn:schemas-microsoft-com:time` style=`behAvior:url(#default#time2)` attributename=`innerhtml` to=`<img/src=\"x\"onerror=alert(24)>`>//[\"'`-->]]>]</div>",
       "expected": "<div id=\"24\">1`>//[\"'`-->]]>]</div>"
   }, {
       "payload": "<div id=\"25\"><script src=\"#\">{alert(25)}</script>;1//[\"'`-->]]>]</div>",
@@ -362,8 +373,8 @@ module.exports = [{
           "<div id=\"36\"><a style=\"-ms-behavior: url(#default#AnchorClick);\">XXX</a>//[\"'`-->]]>]</div>"
       ]
   }, {
-      "payload": "<div id=\"37\"><!--<img src=\"--><img src=x:x onerror=alert(37)//\">//[\"'`-->]]>]</div>",
-      "expected": "<div id=\"37\"><img src=\"x:x\">//[\"'`-->]]>]</div>"
+      "payload": "<div id=\"37\"><!--<img src=\"--><img src=x onerror=alert(37)//\">//[\"'`-->]]>]</div>",
+      "expected": "<div id=\"37\"><img src=\"x\">//[\"'`-->]]>]</div>"
   }, {
       "payload": "<div id=\"38\"><comment><img src=\"</comment><img src=x onerror=alert(38)//\">//[\"'`-->]]>]</div><div id=\"39\"><!-- up to Opera 11.52, FF 3.6.28 -->",
       "expected": [
@@ -379,15 +390,15 @@ module.exports = [{
           "<img src=\"]%3E%3Cimg%20src=x%20onerror=alert%2839%29//\">"
       ]
   }, {
-      "payload": "<!-- IE9+, FF4+, Opera 11.60+, Safari 4.0.4+, GC7+  -->\n<svg><![CDATA[><image xlink:href=\"]]><img src=x:x onerror=alert(2)//\"></svg>//[\"'`-->]]>]</div>",
+      "payload": "<!-- IE9+, FF4+, Opera 11.60+, Safari 4.0.4+, GC7+  -->\n<svg><![CDATA[><image xlink:href=\"]]><img src=x onerror=alert(2)//\"></svg>//[\"'`-->]]>]</div>",
       "expected": [
-          "<svg>><image xlink:href=\"</svg><img src=\"x:x\">//[\"'`-->]]>]",
-          "<svg>><image xlink:href=\"<img src=\"x:x\"></img></svg>//[\"'`-->]]>]",
-          "<svg xmlns=\"http://www.w3.org/2000/svg\">><image xlink:href=\"</svg></svg><img src=\"x:x\">//[\"'`-->]]>]"
+          "<svg>><image xlink:href=\"</svg><img src=\"x\">//[\"'`-->]]>]",
+          "<svg>><image xlink:href=\"<img src=\"x\"></img></svg>//[\"'`-->]]>]",
+          "<svg xmlns=\"http://www.w3.org/2000/svg\">><image xlink:href=\"</svg></svg><img src=\"x\">//[\"'`-->]]>]"
       ]
   }, {
-      "payload": "<div id=\"40\"><style><img src=\"</style><img src=x:x onerror=alert(40)//\">//[\"'`-->]]>]</div>",
-      "expected": "<div id=\"40\"><style><img src=\"</style><img src=\"x:x\">//[\"'`-->]]>]</div>"
+      "payload": "<div id=\"40\"><style><img src=\"</style><img src=x onerror=alert(40)//\">//[\"'`-->]]>]</div>",
+      "expected": "<div id=\"40\"><style><img src=\"</style><img src=\"x\">//[\"'`-->]]>]</div>"
   }, {
       "payload": "<div id=\"41\"><li style=list-style:url() onerror=alert(41)></li>",
       "expected": [
@@ -501,7 +512,7 @@ module.exports = [{
           "<div id=\"65\"><svg xmlns=\"http://www.w3.org/2000/svg\" />//[\"'`-->]]>]</div><div id=\"66\"></div>"
       ]
   }, {
-      "payload": "<?xml-stylesheet type=\"text/xsl\" href=\"data:,%3Cxsl:transform version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' id='xss'%3E%3Cxsl:output method='html'/%3E%3Cxsl:template match='/'%3E%3Cscript%3Ealert(66)%3C/script%3E%3C/xsl:template%3E%3C/xsl:transform%3E\"?>\n<root/>//[\"'`-->]]>]</div>\n<div id=\"67\"><!DOCTYPE x [\n    <!ATTLIST img xmlns CDATA \"http://www.w3.org/1999/xhtml\" src CDATA \"xx:x\"\n onerror CDATA \"alert(67)\"\n onload CDATA \"alert(2)\ [...]
+      "payload": "<?xml-stylesheet type=\"text/xsl\" href=\"data:,%3Cxsl:transform version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' id='xss'%3E%3Cxsl:output method='html'/%3E%3Cxsl:template match='/'%3E%3Cscript%3Ealert(66)%3C/script%3E%3C/xsl:template%3E%3C/xsl:transform%3E\"?>\n<root/>//[\"'`-->]]>]</div>\n<div id=\"67\"><!DOCTYPE x [\n    <!ATTLIST img xmlns CDATA \"http://www.w3.org/1999/xhtml\" src CDATA \"xx\"\n onerror CDATA \"alert(67)\"\n onload CDATA \"alert(2)\"> [...]
       "expected": "//[\"'`-->]]>]\n<div id=\"67\">\n]><img>//[\"'`-->]]>]</div>"
   }, {
       "payload": "<div id=\"68\"><doc xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:html=\"http://www.w3.org/1999/xhtml\">\n    <html:style /><x xlink:href=\"javascript:alert(68)\" xlink:type=\"simple\">XXX</x>\n</doc>//[\"'`-->]]>]</div>",
@@ -543,7 +554,7 @@ module.exports = [{
       "payload": "<div id=\"78\"><?xml-stylesheet type=\"text/xsl\" href=\"#\"?><img xmlns=\"x-schema:test.xdr\"/>//[\"'`-->]]>]</div>",
       "expected": "<div id=\"78\"><img xmlns=\"x-schema:test.xdr\">//[\"'`-->]]>]</div>"
   }, {
-      "payload": "<div id=\"79\"><object allowscriptaccess=\"always\" data=\"x:x\"></object>//[\"'`-->]]>]</div>",
+      "payload": "<div id=\"79\"><object allowscriptaccess=\"always\" data=\"x\"></object>//[\"'`-->]]>]</div>",
       "expected": "<div id=\"79\">//[\"'`-->]]>]</div>"
   }, {
       "payload": "<div id=\"80\"><style>*{x:\uFF45\uFF58\uFF50\uFF52\uFF45\uFF53\uFF53\uFF49\uFF4F\uFF4E(alert(80))}</style>//[\"'`-->]]>]</div>",
@@ -642,8 +653,8 @@ module.exports = [{
           "<div id=\"98\"><div id=\"d\"><div style=\"font-family:'sansFAAFB colorAredB'\">X</div></div>\n//[\"'`-->]]>]</div>"
       ]
   }, {
-      "payload": "<div id=\"99\">XXX<style>\n\n*{color:gre/**/en !/**/important} /* IE 6-9 Standards mode */\n\n<!--\n--><!--*{color:red}   /* all UA */\n\n*{background:url(xx:x //**/\red/*)} /* IE 6-7 Standards mode */\n\n</style>//[\"'`-->]]>]</div>",
-      "expected": "<div id=\"99\">XXX<style>\n\n*{color:gre/**/en !/**/important} /* IE 6-9 Standards mode */\n\n<!--\n--><!--*{color:red}   /* all UA */\n\n*{background:url(xx:x //**/\ned/*)} /* IE 6-7 Standards mode */\n\n</style>//[\"'`-->]]>]</div>"
+      "payload": "<div id=\"99\">XXX<style>\n\n*{color:gre/**/en !/**/important} /* IE 6-9 Standards mode */\n\n<!--\n--><!--*{color:red}   /* all UA */\n\n*{background:url(xx //**/\red/*)} /* IE 6-7 Standards mode */\n\n</style>//[\"'`-->]]>]</div>",
+      "expected": "<div id=\"99\">XXX<style>\n\n*{color:gre/**/en !/**/important} /* IE 6-9 Standards mode */\n\n<!--\n--><!--*{color:red}   /* all UA */\n\n*{background:url(xx //**/\ned/*)} /* IE 6-7 Standards mode */\n\n</style>//[\"'`-->]]>]</div>"
   }, {
       "payload": "<div id=\"100\"><img[a][b]src=x[d]onerror[c]=[e]\"alert(100)\">//[\"'`-->]]>]</div>",
       "expected": "<div id=\"100\">//[\"'`-->]]>]</div>"
@@ -680,11 +691,11 @@ module.exports = [{
       "payload": "<div id=\"107\"><title onpropertychange=alert(107)></title><title title=></title>//[\"'`-->]]>]</div>",
       "expected": "<div id=\"107\"><title></title><title title=\"\"></title>//[\"'`-->]]>]</div>"
   }, {
-      "payload": "<div id=\"108\"><!-- IE 5-8 standards mode -->\n<a href=http://foo.bar/#x=`y></a><img alt=\"`><img src=xx:x onerror=alert(108)></a>\">\n<!-- IE 5-9 standards mode -->\n<!a foo=x=`y><img alt=\"`><img src=xx:x onerror=alert(2)//\">\n<?a foo=x=`y><img alt=\"`><img src=xx:x onerror=alert(3)//\">//[\"'`-->]]>]</div>",
+      "payload": "<div id=\"108\"><!-- IE 5-8 standards mode -->\n<a href=http://foo.bar/#x=`y></a><img alt=\"`><img src=xx onerror=alert(108)></a>\">\n<!-- IE 5-9 standards mode -->\n<!a foo=x=`y><img alt=\"`><img src=xx onerror=alert(2)//\">\n<?a foo=x=`y><img alt=\"`><img src=xx onerror=alert(3)//\">//[\"'`-->]]>]</div>",
       "expected": [
-          "<div id=\"108\">\n<a href=\"http://foo.bar/#x=`y\"></a><img alt=\"`><img src=xx:x onerror=alert(108)></a>\">\n\n<img alt=\"`><img src=xx:x onerror=alert(2)//\">\n<img alt=\"`><img src=xx:x onerror=alert(3)//\">//[\"'`-->]]>]</div>",
-          "<div id=\"108\">\n<a href=\"http://foo.bar/#x=`y\"></a><img alt=\"`><img src=xx:x onerror=alert(108)></a>\">\n\n<img alt=\"`><img src=xx:x onerror=alert(2)//\">\n<img alt=\"`><img src=xx:x onerror=alert(3)//\">//[\"'`-->]]>]</div>",
-          "<div id=\"108\">\n<a href=\"http://foo.bar/#x=%60y\"></a><img alt=\"`><img src=xx:x onerror=alert(108)></a>\">\n\n<img alt=\"`><img src=xx:x onerror=alert(2)//\">\n<img alt=\"`><img src=xx:x onerror=alert(3)//\">//[\"'`-->]]>]</div>"
+          "<div id=\"108\">\n<a href=\"http://foo.bar/#x=`y\"></a><img alt=\"`><img src=xx onerror=alert(108)></a>\">\n\n<img alt=\"`><img src=xx onerror=alert(2)//\">\n<img alt=\"`><img src=xx onerror=alert(3)//\">//[\"'`-->]]>]</div>",
+          "<div id=\"108\">\n<a href=\"http://foo.bar/#x=`y\"></a><img alt=\"`><img src=xx onerror=alert(108)></a>\">\n\n<img alt=\"`><img src=xx onerror=alert(2)//\">\n<img alt=\"`><img src=xx onerror=alert(3)//\">//[\"'`-->]]>]</div>",
+          "<div id=\"108\">\n<a href=\"http://foo.bar/#x=%60y\"></a><img alt=\"`><img src=xx onerror=alert(108)></a>\">\n\n<img alt=\"`><img src=xx onerror=alert(2)//\">\n<img alt=\"`><img src=xx onerror=alert(3)//\">//[\"'`-->]]>]</div>"
       ]
   }, {
       "payload": "<div id=\"109\"><svg xmlns=\"http://www.w3.org/2000/svg\">\n<a id=\"x\"><rect fill=\"white\" width=\"1000\" height=\"1000\"/></a>\n<rect  fill=\"white\" style=\"clip-path:url(test3.svg#a);fill:url(#b);filter:url(#c);marker:url(#d);mask:url(#e);stroke:url(#f);\"/>\n</svg>//[\"'`-->]]>]</div>",
@@ -720,7 +731,7 @@ module.exports = [{
       "expected": "<div id=\"114\">XXX//[\"'`-->]]>]</div><div id=\"115\">\n//[\"'`-->]]>]</div>"
   }, {
       "title": "XML",
-      "payload": "<div id=\"116\"><div id=\"x\">x</div>\n<xml:namespace prefix=\"t\">\n<import namespace=\"t\" implementation=\"#default#time2\">\n<t:set attributeName=\"innerHTML\" targetElement=\"x\" to=\"<img\u000Bsrc=x:x\u000Bonerror\u000B=alert(116)>\">//[\"'`-->]]>]</div>",
+      "payload": "<div id=\"116\"><div id=\"x\">x</div>\n<xml:namespace prefix=\"t\">\n<import namespace=\"t\" implementation=\"#default#time2\">\n<t:set attributeName=\"innerHTML\" targetElement=\"x\" to=\"<img\u000Bsrc=x\u000Bonerror\u000B=alert(116)>\">//[\"'`-->]]>]</div>",
       "expected": "<div id=\"116\"><div id=\"x\">x</div>\n\n\n//[\"'`-->]]>]</div>"
   }, {
       "title": "iframe",
@@ -780,11 +791,11 @@ module.exports = [{
           "<div id=\"127\"><svg xmlns=\"http://www.w3.org/2000/svg\" id=\"x\">\n\n\n</svg>//[\"'`-->]]>]</div>"
       ]
   }, {
-      "payload": "<div id=\"128\"><svg><style><img/src=x:x onerror=alert(128)// </b>//[\"'`-->]]>]</div>",
+      "payload": "<div id=\"128\"><svg><style><img/src=x onerror=alert(128)// </b>//[\"'`-->]]>]</div>",
       "expected": [
-          "<div id=\"128\"><svg><style></style></svg><img src=\"x:x\">//[\"'`-->]]>]</div>",
-          "<div id=\"128\"><svg><style><img src=\"x:x\">//[\"'`-->]]>]</img></style></svg></div>",
-          "<div id=\"128\"><svg xmlns=\"http://www.w3.org/2000/svg\"><style /></svg></svg><img src=\"x:x\">//[\"'`-->]]>]</div>"
+          "<div id=\"128\"><svg><style></style></svg><img src=\"x\">//[\"'`-->]]>]</div>",
+          "<div id=\"128\"><svg><style><img src=\"x\">//[\"'`-->]]>]</img></style></svg></div>",
+          "<div id=\"128\"><svg xmlns=\"http://www.w3.org/2000/svg\"><style /></svg></svg><img src=\"x\">//[\"'`-->]]>]</div>"
       ]
   }, {
       "title": "Inline SVG (data-uri)",
@@ -817,14 +828,14 @@ module.exports = [{
           "<div id=\"132\">\n<form>\n<label>type a,b,c,d - watch the network tab/traffic (JS is off, latest NoScript)</label>\n<br>\n<input name=\"secret\" type=\"password\">\n</form>\n<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"50px\">\n<image xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n\n\n\n\n</image>\n</svg>//[\"'`-->]]>]</div>"
         ]
   }, {
-      "payload": "<div id=\"133\"><!-- `<img/src=xx:xx onerror=alert(133)//--!>//[\"'`-->]]>]</div>",
+      "payload": "<div id=\"133\"><!-- `<img/src=xxx onerror=alert(133)//--!>//[\"'`-->]]>]</div>",
       "expected": "<div id=\"133\">//[\"'`-->]]>]</div>"
   }, {
       "title": "XMP",
-      "payload": "<div id=\"134\"><xmp>\n<%\n</xmp>\n<img alt='%></xmp><img src=xx:x onerror=alert(134)//'>\n\n<script>\nx='<%'\n</script> %>/\nalert(2)\n</script>\n\nXXX\n<style>\n*['<!--']{}\n</style>\n-->{}\n*{color:red}</style>//[\"'`-->]]>]</div>",
+      "payload": "<div id=\"134\"><xmp>\n<%\n</xmp>\n<img alt='%></xmp><img src=xx onerror=alert(134)//'>\n\n<script>\nx='<%'\n</script> %>/\nalert(2)\n</script>\n\nXXX\n<style>\n*['<!--']{}\n</style>\n-->{}\n*{color:red}</style>//[\"'`-->]]>]</div>",
       "expected": [
-          "<div id=\"134\">\n<%\n\n<img alt=\"%></xmp><img src=xx:x onerror=alert(134)//\">\n\n %>/\nalert(2)\n\n\nXXX\n<style>\n*['<!--']{}\n</style>\n-->{}\n*{color:red}//[\"'`-->]]>]</div>",
-          "<div id=\"134\">\n<%\n\n<img alt=\"%></xmp><img src=xx:x onerror=alert(134)//\">\n\n %>/\nalert(2)\n\n\nXXX\n<style>\n*['<!--']{}\n</style>\n-->{}\n*{color:red}//[\"'`-->]]>]</div>"
+          "<div id=\"134\">\n<%\n\n<img alt=\"%></xmp><img src=xx onerror=alert(134)//\">\n\n %>/\nalert(2)\n\n\nXXX\n<style>\n*['<!--']{}\n</style>\n-->{}\n*{color:red}//[\"'`-->]]>]</div>",
+          "<div id=\"134\">\n<%\n\n<img alt=\"%></xmp><img src=xx onerror=alert(134)//\">\n\n %>/\nalert(2)\n\n\nXXX\n<style>\n*['<!--']{}\n</style>\n-->{}\n*{color:red}//[\"'`-->]]>]</div>"
       ]
   }, {
       "title": "SVG",
@@ -834,12 +845,12 @@ module.exports = [{
           "<div id=\"135\">\n\n<template>\nnew ActiveXObject('htmlfile').parentWindow.alert(135)\n\n</template>\n//[\"'`-->]]>]</div>"
       ]
   }, {
-      "payload": "<div id=\"136\"><form action=\"\" method=\"post\">\n<input name=\"username\" value=\"admin\" />\n<input name=\"password\" type=\"password\" value=\"secret\" />\n<input name=\"injected\" value=\"injected\" dirname=\"password\" />\n<input type=\"submit\">\n</form>//[\"'`-->]]>]</div>",
+      "payload": "<div id=\"136\"><form action=\"x\" method=\"post\">\n<input name=\"username\" value=\"admin\" />\n<input name=\"password\" type=\"password\" value=\"secret\" />\n<input name=\"injected\" value=\"injected\" dirname=\"password\" />\n<input type=\"submit\">\n</form>//[\"'`-->]]>]</div>",
       "expected": [
-          "<div id=\"136\"><form method=\"post\" action=\"\">\n<input value=\"admin\" name=\"username\">\n<input value=\"secret\" type=\"password\" name=\"password\">\n<input value=\"injected\" name=\"injected\">\n<input type=\"submit\">\n</form>//[\"'`-->]]>]</div>",
-          "<div id=\"136\"><form method=\"post\" action=\"\">\n<input value=\"admin\" name=\"username\">\n<input value=\"secret\" type=\"password\" name=\"password\">\n<input value=\"injected\" name=\"injected\">\n<input type=\"submit\">\n//[\"'`-->]]>]</form></div>",
-          "<div id=\"136\"><form method=\"post\" action=\"\">\n<input value=\"admin\" name=\"username\">\n<input value=\"secret\" name=\"password\" type=\"password\">\n<input value=\"injected\" name=\"injected\">\n<input type=\"submit\">\n</form>//[\"'`-->]]>]</div>",
-          "<div id=\"136\"><form action=\"\" method=\"post\">\n<input name=\"username\" value=\"admin\">\n<input name=\"password\" type=\"password\" value=\"secret\">\n<input name=\"injected\" value=\"injected\">\n<input type=\"submit\" value=\"Submit Query\">\n</form>//[\"'`-->]]>]</div>"
+          "<div id=\"136\"><form method=\"post\" action=\"x\">\n<input value=\"admin\" name=\"username\">\n<input value=\"secret\" type=\"password\" name=\"password\">\n<input value=\"injected\" name=\"injected\">\n<input type=\"submit\">\n</form>//[\"'`-->]]>]</div>",
+          "<div id=\"136\"><form method=\"post\" action=\"x\">\n<input value=\"admin\" name=\"username\">\n<input value=\"secret\" type=\"password\" name=\"password\">\n<input value=\"injected\" name=\"injected\">\n<input type=\"submit\">\n//[\"'`-->]]>]</form></div>",
+          "<div id=\"136\"><form method=\"post\" action=\"x\">\n<input value=\"admin\" name=\"username\">\n<input value=\"secret\" name=\"password\" type=\"password\">\n<input value=\"injected\" name=\"injected\">\n<input type=\"submit\">\n</form>//[\"'`-->]]>]</div>",
+          "<div id=\"136\"><form action=\"x\" method=\"post\">\n<input name=\"username\" value=\"admin\">\n<input name=\"password\" type=\"password\" value=\"secret\">\n<input name=\"injected\" value=\"injected\">\n<input type=\"submit\" value=\"Submit Query\">\n</form>//[\"'`-->]]>]</div>"
       ]
   }, {
       "title": "SVG",
diff --git a/test/test-suite.js b/test/test-suite.js
index ae0d08d..e97c290 100644
--- a/test/test-suite.js
+++ b/test/test-suite.js
@@ -78,6 +78,7 @@ module.exports = function(DOMPurify, tests, xssTests) {
           ["<b>he  ya</b>", "<b>he </b>", "<b>he <form><img src=\"x\"></form> ya</b>"] // Investigate on Safari 8! 
       );
       assert.equal( DOMPurify.sanitize( '<a>123<% <b>456}}</b><style>{{ alert(1) }}</style>456 %></a>', {SAFE_FOR_TEMPLATES: true}), "<a>123 <b> </b><style> </style> </a>" );
+      assert.equal( DOMPurify.sanitize( '<a href="}}javascript:alert(1)"></a>', {SAFE_FOR_TEMPLATES: true}), "<a></a>" );
   }); 
   QUnit.test( 'Config-Flag tests: SANITIZE_DOM', function(assert) {
       // SANITIZE_DOM
diff --git a/website/index.html b/website/index.html
index 24f19bc..a09fa20 100644
--- a/website/index.html
+++ b/website/index.html
@@ -2,7 +2,7 @@
 <html>
     <head>
         <meta charset="UTF-8">
-        <title>DOMPurify 0.7.3 "Black Mamba"</title>
+        <title>DOMPurify 0.7.4 "Common Snapping Turtle"</title>
         <script src="../dist/purify.min.js"></script>
         <!-- we don't actually need it - just to demo and test the $(html) sanitation -->
         <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
@@ -23,7 +23,7 @@
         </script>
     </head>
     <body>
-        <h4>DOMPurify 0.7.3 "Black Mamba"</h4>
+        <h4>DOMPurify 0.7.4 "Common Snapping Turtle"</h4>
         <p>
             <a href="http://badge.fury.io/bo/dompurify"><img style="max-width:100%;" alt="Bower version" src="https://badge.fury.io/bo/dompurify.svg"></a> · <a href="http://badge.fury.io/js/dompurify"><img style="max-width:100%;" alt="npm version" src="https://badge.fury.io/js/dompurify.svg"></a> · <a href="https://travis-ci.org/cure53/DOMPurify"><img style="max-width:100%;" alt="Build Status" src="https://travis-ci.org/cure53/DOMPurify.svg?branch=master"></a>
         </p>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/dompurify.js.git



More information about the Pkg-javascript-commits mailing list