Skip to content

Commit

Permalink
see #14
Browse files Browse the repository at this point in the history
# added DOM clobbering protection for output
# added new config flag SANTIZE_DOM, default true
# updated README with new config options
  • Loading branch information
mario committed Mar 8, 2014
1 parent ee0ffc6 commit 78037ea
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 16 deletions.
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,26 @@ DOMPurify currently supports HTML5, SVG and MathML. DOMPurify per default allows
Yes. The included default configuration values are pretty good already - but you can of course override them:
```javascript
// Allow only <b>
// allow only <b>
var clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b']});

// Allow only <b> with style attributes (for whatever reason)
var clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b'], ALLOWED_ATTR: ['style']});
// allow only <b> with style attributes (for whatever reason)
var clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b', 'q'], ALLOWED_ATTR: ['style']});

// prohibit HTML5 data attributes
var clean = DOMPurify.sanitize(dirty, {ALLOW_DATA_ATTR: false});

// return a DOM instead of a HTML string
var clean = DOMPurify.sanitize(dirty, {RETURN_DOM: true});

// return entire document including <html> tags
var clean = DOMPurify.sanitize(dirty, {WHOLE_DOCUMENT: true});

// make output safe for usage in jQuery's $() method
var clean = DOMPurify.sanitize(dirty, {SAFE_FOR_JQUERY: true});

// disable DOM Clobbering protection on output (handle with care!)
var clean = DOMPurify.sanitize(dirty, {SANITIZE_DOM: false});
```
## What's on the road-map?
Expand Down
29 changes: 16 additions & 13 deletions purify.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@

/* Output should be safe for jQuery's $() factory? */
var SAFE_FOR_JQUERY = false;

/* Output should be free from DOM clobbering attacks? */
var SANITIZE_DOM = true;

/* Ideally, do not touch anything below this line */
/* ______________________________________________ */


/**
* _parseConfig
*
Expand All @@ -116,9 +118,9 @@
cfg.SAFE_FOR_JQUERY ? SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY : null;
cfg.WHOLE_DOCUMENT ? WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT : null;
cfg.RETURN_DOM ? RETURN_DOM = cfg.RETURN_DOM : null;
cfg.SANITIZE_DOM ? SANITIZE_DOM = cfg.SANITIZE_DOM : null;
};


/**
* _createIterator
*
Expand All @@ -134,7 +136,6 @@
);
};


/**
* _isClobbered
*
Expand All @@ -144,7 +145,7 @@
var _isClobbered = function(elm) {
if (
(elm.children && !(elm.children instanceof HTMLCollection))
|| typeof elm.nodeName !== 'string'
|| typeof elm.nodeName !== 'string'
|| typeof elm.textContent !== 'string'
|| typeof elm.nodeType !== 'number'
|| typeof elm.COMMENT_NODE !== 'number'
Expand All @@ -158,7 +159,6 @@
return false;
};


/**
* _sanitizeElements
*
Expand Down Expand Up @@ -186,7 +186,6 @@
return false;
};


/**
* _sanitizeAttributes
*
Expand All @@ -204,21 +203,30 @@

for (var attr = currentNode.attributes.length-1; attr >= 0; attr--) {
var tmp = clonedNode.attributes[attr];
var clobbering = false;
currentNode.removeAttribute(currentNode.attributes[attr].name);

if (tmp instanceof Attr) {
if(SANITIZE_DOM) {
if(tmp.name === 'id' && window[tmp.value]) {
var clobbering = true;
}
if(tmp.name === 'name' && document[tmp.value]){
var clobbering = true;
}
}
if (
(ALLOWED_ATTR.indexOf(tmp.name.toLowerCase()) > -1 ||
(ALLOW_DATA_ATTR && tmp.name.match(/^data-[\w-]+/i)))
&& !tmp.value.replace(/[\x00-\x20]/g,'').match(regex)
&& !clobbering
) {
currentNode.setAttribute(tmp.name, tmp.value);
}
}
}
};


/**
* _sanitizeShadowDOM
*
Expand All @@ -245,17 +253,14 @@
}
};


/* Assign config vars */
cfg ? _parseConfig(cfg) : null;


/* Create documents to map markup to */
var dom = document.implementation.createHTMLDocument('');
dom.body.parentNode.removeChild(dom.body.parentNode.firstElementChild);
dom.body.outerHTML = dirty;
var body = WHOLE_DOCUMENT ? dom.body.parentNode : dom.body;

if (
!(dom.body instanceof HTMLBodyElement) ||
!(dom.body instanceof HTMLHtmlElement)
Expand All @@ -265,17 +270,16 @@
? freshdom.getElementsByTagName.call(dom,'html')[0]
: freshdom.getElementsByTagName.call(dom,'body')[0];
}

/* Early exit in case document is empty */
if(typeof body === 'undefined') {
return '';
}


/* Get node iterator */
var currentNode;
var nodeIterator = _createIterator(body);


/* Now start iterating over the created document */
while (currentNode = nodeIterator.nextNode()) {
/* Sanitize tags and elements */
Expand All @@ -292,7 +296,6 @@
_sanitizeAttributes(currentNode);
}


/* Return sanitized string or DOM */
if (RETURN_DOM) {
return body;
Expand Down

0 comments on commit 78037ea

Please sign in to comment.