Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 7f57c68

Browse files
committed
fix($sanitize): remove browser bug detections from inert strategy selection
Default to using DOMParser if it is available and fall back to createHTMLDocument if needed. This is the approach suggested in the related pull request #17013 and used by DOMPurify too. It also safely avoids using an inline style tag that causes CSP violation errors if inline CSS is prohibited. The related unit tests in `sanitizeSpec.js`, "should not allow JavaScript execution when creating inert document" and "should not allow JavaScript hidden in badly formed HTML to get through sanitization (Firefox bug)", are left untouched to assert that the behavior hasn't changed in those scenarios. Fixes #16463.
1 parent 418355f commit 7f57c68

File tree

1 file changed

+13
-35
lines changed

1 file changed

+13
-35
lines changed

src/ngSanitize/sanitize.js

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -421,50 +421,28 @@ function $SanitizeProvider() {
421421
}
422422

423423
/**
424-
* Create an inert document that contains the dirty HTML that needs sanitizing
425-
* Depending upon browser support we use one of three strategies for doing this.
426-
* Support: Safari 10.x -> XHR strategy
427-
* Support: Firefox -> DomParser strategy
424+
* Create an inert document that contains the dirty HTML that needs sanitizing.
425+
* We use the DOMParser API by default and fall back to createHTMLDocument if DOMParser is not
426+
* available.
428427
*/
429428
var getInertBodyElement /* function(html: string): HTMLBodyElement */ = (function(window, document) {
430-
var inertDocument;
431-
if (document && document.implementation) {
432-
inertDocument = document.implementation.createHTMLDocument('inert');
433-
} else {
434-
throw $sanitizeMinErr('noinert', 'Can\'t create an inert html document');
429+
if (isDOMParserAvailable()) {
430+
return getInertBodyElement_DOMParser;
435431
}
436-
var inertBodyElement = (inertDocument.documentElement || inertDocument.getDocumentElement()).querySelector('body');
437432

438-
// Check for the Safari 10.1 bug - which allows JS to run inside the SVG G element
439-
inertBodyElement.innerHTML = '<svg><g onload="this.parentNode.remove()"></g></svg>';
440-
if (!inertBodyElement.querySelector('svg')) {
441-
return getInertBodyElement_XHR;
442-
} else {
443-
// Check for the Firefox bug - which prevents the inner img JS from being sanitized
444-
inertBodyElement.innerHTML = '<svg><p><style><img src="</style><img src=x onerror=alert(1)//">';
445-
if (inertBodyElement.querySelector('svg img')) {
446-
return getInertBodyElement_DOMParser;
447-
} else {
448-
return getInertBodyElement_InertDocument;
449-
}
433+
if (!document || !document.implementation) {
434+
throw $sanitizeMinErr('noinert', 'Can\'t create an inert html document');
450435
}
436+
var inertDocument = document.implementation.createHTMLDocument('inert');
437+
var inertBodyElement = (inertDocument.documentElement || inertDocument.getDocumentElement()).querySelector('body');
438+
return getInertBodyElement_InertDocument;
451439

452-
function getInertBodyElement_XHR(html) {
453-
// We add this dummy element to ensure that the rest of the content is parsed as expected
454-
// e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the `<head>` tag.
455-
html = '<remove></remove>' + html;
440+
function isDOMParserAvailable() {
456441
try {
457-
html = encodeURI(html);
442+
return !!getInertBodyElement_DOMParser('');
458443
} catch (e) {
459-
return undefined;
444+
return false;
460445
}
461-
var xhr = new window.XMLHttpRequest();
462-
xhr.responseType = 'document';
463-
xhr.open('GET', 'data:text/html;charset=utf-8,' + html, false);
464-
xhr.send(null);
465-
var body = xhr.response.body;
466-
body.firstChild.remove();
467-
return body;
468446
}
469447

470448
function getInertBodyElement_DOMParser(html) {

0 commit comments

Comments
 (0)