1. 8.4 Dynamic markup insertion
      1. 8.4.1 Opening the input stream
      2. 8.4.2 Closing the input stream
      3. 8.4.3 document.write()
      4. 8.4.4 document.writeln()
    2. 8.5 DOM parsing and serialization APIs
      1. 8.5.1 The DOMParser interface
      2. 8.5.2 Unsafe HTML parsing methods
      3. 8.5.3 Safe HTML parsing methods
      4. 8.5.4 HTML serialization methods
      5. 8.5.4 8.5.5 The innerHTML property
      6. 8.5.5 8.5.6 The outerHTML property
      7. 8.5.6 8.5.7 The insertAdjacentHTML() method
      8. 8.5.7 8.5.8 The createContextualFragment() method
      9. 8.5.8 8.5.9 The XMLSerializer interface
    3. 8.6 HTML sanitization
      1. 8.6.1 Introduction
      2. 8.6.2 The Sanitizer interface
      3. 8.6.3 Sanitizer configuration
        1. 8.6.3.1 Configuration invariants
      4. 8.6.4 Processing model
      5. 8.6.5 Sanitization algorithms
      6. 8.6.6 Sanitization constants

8.4 Dynamic markup insertion

APIs for dynamically inserting markup into the document interact with the parser, and thus their behavior varies depending on whether they are used with HTML documents (and the HTML parser ) or XML documents (and the XML parser ).

Document objects have a throw-on-dynamic-markup-insertion counter , which is used in conjunction with the create an element for the token algorithm to prevent custom element constructors from being able to use document.open() , document.close() , and document.write() when they are invoked by the parser. Initially, the counter must be set to zero.

8.4.1 Opening the input stream

document = document . open ()

Document/open

Support in all current engines.

Firefox 1+ Safari 11+ Chrome 64+
Opera 51+ Edge 79+
Edge (Legacy) 12+ Internet Explorer 4+
Firefox Android ? Safari iOS ? Chrome Android ? WebView Android ? Samsung Internet ? Opera Android 47+

Causes the Document to be replaced in-place, as if it was a new Document object, but reusing the previous object, which is then returned.

The resulting Document has an HTML parser associated with it, which can be given data to parse using document.write() .

The method has no effect if the Document is still being parsed.

Throws an " InvalidStateError " DOMException if the Document is an XML document .

Throws an " InvalidStateError " DOMException if the parser is currently executing a custom element constructor .

window = document . open ( url , name , features )

Works like the window.open() method.

Document objects have an active parser was aborted boolean, which is used to prevent scripts from invoking the document.open() and document.write() methods (directly or indirectly) after the document's active parser has been aborted. It is initially false.

The document open steps , given a document , are as follows:

  1. If document is an XML document , then throw an " InvalidStateError " DOMException .

  2. If document 's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an " InvalidStateError " DOMException .

  3. Let entryDocument be the entry global object 's associated Document .

  4. If document 's origin is not same origin to entryDocument 's origin , then throw a " SecurityError " DOMException .

  5. If document has an active parser whose script nesting level is greater than 0, then return document .

    This basically causes document.open() to be ignored when it's called in an inline script found during parsing, while still letting it have an effect when called from a non-parser task such as a timer callback or event handler.

  6. Similarly, if document 's unload counter is greater than 0, then return document .

    This basically causes document.open() to be ignored when it's called from a beforeunload , pagehide , or unload event handler while the Document is being unloaded.

  7. If document 's active parser was aborted is true, then return document .

    This notably causes document.open() to be ignored if it is called after a navigation has started, but only during the initial parse. See issue #4723 for more background.

  8. If document 's node navigable is non-null and document 's node navigable 's ongoing navigation is a navigation ID , then stop loading document 's node navigable .

  9. For each shadow-including inclusive descendant node of document , erase all event listeners and handlers given node .

  10. If document is the associated Document of document 's relevant global object , then erase all event listeners and handlers given document 's relevant global object .

  11. Replace all with null within document .

  12. If document is fully active , then:

    1. Let newURL be a copy of entryDocument 's URL .

    2. If entryDocument is not document , then set newURL 's fragment to null.

    3. Run the URL and history update steps with document and newURL .

  13. Set document 's is initial about:blank to false.

  14. If document 's iframe load in progress flag is set, then set document 's mute iframe load flag.

  15. Set document to no-quirks mode .

  16. Create a new HTML parser and associate it with document . This is a script-created parser (meaning that it can be closed by the document.open() and document.close() methods, and that the tokenizer will wait for an explicit call to document.close() before emitting an end-of-file token). The encoding confidence is irrelevant .

  17. Set the insertion point to point at just before the end of the input stream (which at this point will be empty).

  18. Update the current document readiness of document to " loading ".

    This causes a readystatechange event to fire, but the event is actually unobservable to author code, because of the previous step which erased all event listeners and handlers that could observe it.

  19. Return document .

The document open steps do not affect whether a Document is ready for post-load tasks or completely loaded .

The open( unused1 , unused2 ) method must return the result of running the document open steps with this .

The unused1 and unused2 arguments are ignored, but kept in the IDL to allow code that calls the function with one or two arguments to continue working. They are necessary due to Web IDL overload resolution algorithm rules, which would throw a TypeError exception for such calls had the arguments not been there. whatwg/webidl issue #581 investigates changing the algorithm to allow for their removal. [WEBIDL]

The open( url , name , features ) method must run these steps:

  1. If this is not fully active , then throw an " InvalidAccessError " DOMException .

  2. Return the result of running the window open steps with url , name , and features .

8.4.2 Closing the input stream

document . close ()

Document/close

Support in all current engines.

Firefox 1+ Safari 11+ Chrome 64+
Opera 51+ Edge 79+
Edge (Legacy) 12+ Internet Explorer 4+
Firefox Android ? Safari iOS ? Chrome Android ? WebView Android ? Samsung Internet ? Opera Android 47+

Closes the input stream that was opened by the document.open() method.

Throws an " InvalidStateError " DOMException if the Document is an XML document .

Throws an " InvalidStateError " DOMException if the parser is currently executing a custom element constructor .

The close() method must run the following steps:

  1. If this is an XML document , then throw an " InvalidStateError " DOMException .

  2. If this 's throw-on-dynamic-markup-insertion counter is greater than zero, then throw an " InvalidStateError " DOMException .

  3. If there is no script-created parser associated with this , then return.

  4. Insert an explicit "EOF" character at the end of the parser's input stream .

  5. If this 's pending parsing-blocking script is not null, then return.

  6. Run the tokenizer, processing resulting tokens as they are emitted, and stopping when the tokenizer reaches the explicit "EOF" character or spins the event loop .

8.4.3 document.write()

document . write (... text )

Document/write

Support in all current engines.

Firefox 1+ Safari 1+ Chrome 1+
Opera 3+ Edge 79+
Edge (Legacy) 12+ Internet Explorer 4+
Firefox Android ? Safari iOS ? Chrome Android ? WebView Android ? Samsung Internet ? Opera Android 10.1+

In general, adds the given string(s) to the Document 's input stream.

This method has very idiosyncratic behavior. In some cases, this method can affect the state of the HTML parser while the parser is running, resulting in a DOM that does not correspond to the source of the document (e.g. if the string written is the string " <plaintext> " or " <!-- "). In other cases, the call can clear the current page first, as if document.open() had been called. In yet more cases, the method is simply ignored, or throws an exception. User agents are explicitly allowed to avoid executing script elements inserted via this method . And to make matters even worse, the exact behavior of this method can in some cases be dependent on network latency, which can lead to failures that are very hard to debug. For all these reasons, use of this method is strongly discouraged.

Throws an " InvalidStateError " DOMException when invoked on XML documents .

Throws an " InvalidStateError " DOMException if the parser is currently executing a custom element constructor .

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes .

Document objects have an ignore-destructive-writes counter , which is used in conjunction with the processing of script elements to prevent external scripts from being able to use document.write() to blow away the document by implicitly calling document.open() . Initially, the counter must be set to zero.

The document write steps , given a Document object document , a list text , a boolean lineFeed , and a string sink , are as follows:

  1. Let string be the empty string.

  2. Let isTrusted be false if text contains a string; otherwise true.

  3. For each value of text :

    1. If value is a TrustedHTML object, then append value 's associated data to string .

    2. Otherwise, append value to string .

  4. If isTrusted is false, set string to the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , string , sink , and " script ".

  5. If lineFeed is true, append U+000A LINE FEED to string .

  6. If document is an XML document , then throw an " InvalidStateError " DOMException .

  7. If document 's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an " InvalidStateError " DOMException .

  8. If document 's active parser was aborted is true, then return.

  9. If the insertion point is undefined, then:

    1. If document 's unload counter is greater than 0 or document 's ignore-destructive-writes counter is greater than 0, then return.

    2. Run the document open steps with document .

  10. Insert string into the input stream just before the insertion point .

  11. If document 's pending parsing-blocking script is null, then have the HTML parser process string , one code point at a time, processing resulting tokens as they are emitted, and stopping when the tokenizer reaches the insertion point or when the processing of the tokenizer is aborted by the tree construction stage (this can happen if a script end tag token is emitted by the tokenizer).

    If the document.write() method was called from script executing inline (i.e. executing because the parser parsed a set of script tags), then this is a reentrant invocation of the parser . If the parser pause flag is set, the tokenizer will abort immediately and no HTML will be parsed, per the tokenizer's parser pause flag check .

The document.write(... text ) method steps are to run the document write steps with this , text , false, and " Document write ".

8.4.4 document.writeln()

document . writeln (... text )

Document/writeln

Support in all current engines.

Firefox 1+ Safari 11+ Chrome 64+
Opera 51+ Edge 79+
Edge (Legacy) 12+ Internet Explorer 4+
Firefox Android ? Safari iOS ? Chrome Android ? WebView Android ? Samsung Internet ? Opera Android 47+

Adds the given string(s) to the Document 's input stream, followed by a newline character. If necessary, calls the open() method implicitly first.

This method has very idiosyncratic behavior. Use of this method is strongly discouraged, for the same reasons as document.write() .

Throws an " InvalidStateError " DOMException when invoked on XML documents .

Throws an " InvalidStateError " DOMException if the parser is currently executing a custom element constructor .

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes .

The document.writeln(... text ) method steps are to run the document write steps with this , text , true, and " Document writeln ".

8.5 DOM parsing and serialization APIs

DOMParser

Support in all current engines.

Firefox 1+ Safari 1.3+ Chrome 1+
Opera 8+ Edge 79+
Edge (Legacy) 12+ Internet Explorer 9+
Firefox Android ? Safari iOS ? Chrome Android ? WebView Android ? Samsung Internet ? Opera Android 10.1+
partial interface Element {
  [ or DOMString) html);

  [CEReactions] undefined setHTMLUnsafe((TrustedHTML or DOMString) html, optional SetHTMLUnsafeOptions options = {});
  [CEReactions] undefined setHTML(DOMString html, optional SetHTMLOptions options = {});

  DOMString getHTML(optional GetHTMLOptions options = {});
  [CEReactions] attribute (TrustedHTML or [LegacyNullToEmptyString] DOMString) innerHTML;
  [CEReactions] attribute (TrustedHTML or [LegacyNullToEmptyString] DOMString) outerHTML;
  [CEReactions] undefined insertAdjacentHTML(DOMString position, (TrustedHTML or DOMString) string);
};
partial interface ShadowRoot {
  [ or DOMString) html);

  [CEReactions] undefined setHTMLUnsafe((TrustedHTML or DOMString) html, optional SetHTMLUnsafeOptions options = {});
  [CEReactions] undefined setHTML(DOMString html, optional SetHTMLOptions options = {});

  DOMString getHTML(optional GetHTMLOptions options = {});
  [CEReactions] attribute (TrustedHTML or [LegacyNullToEmptyString] DOMString) innerHTML;
};
enum SanitizerPresets { "default" };
dictionary SetHTMLOptions {
  (Sanitizer or SanitizerConfig or SanitizerPresets) sanitizer = "default";
};
dictionary SetHTMLUnsafeOptions {
  (Sanitizer or SanitizerConfig or SanitizerPresets) sanitizer = {};
};

dictionary GetHTMLOptions {
  boolean serializableShadowRoots = false;
  sequence<ShadowRoot> shadowRoots = [];
};

8.5.1 The DOMParser interface

The DOMParser interface allows authors to create new Document objects by parsing strings, as either HTML or XML.

parser = new DOMParser ()

DOMParser/DOMParser

Support in all current engines.

Firefox 1+ Safari 1.3+ Chrome 1+
Opera 8+ Edge 79+
Edge (Legacy) 12+ Internet Explorer 9+
Firefox Android ? Safari iOS ? Chrome Android ? WebView Android ? Samsung Internet ? Opera Android 10.1+

Constructs a new DOMParser object.

document = parser . parseFromString ( string , type )

DOMParser/parseFromString

Support in all current engines.

Firefox 1+ Safari 1.3+ Chrome 1+
Opera 8+ Edge 79+
Edge (Legacy) 12+ Internet Explorer 9+
Firefox Android ? Safari iOS ? Chrome Android ? WebView Android ? Samsung Internet ? Opera Android 10.1+

Parses string using either the HTML or XML parser, according to type , and returns the resulting Document . type can be " text/html " (which will invoke the HTML parser), or any of " text/xml ", " application/xml ", " application/xhtml+xml ", or " image/svg+xml " (which will invoke the XML parser).

For the XML parser, if string cannot be parsed, then the returned Document will contain elements describing the resulting error.

Note that script elements are not evaluated during parsing, and the resulting document's encoding will always be UTF-8 . The document's URL will be inherited from parser 's relevant global object .

Values other than the above for type will cause a TypeError exception to be thrown.

The design of DOMParser , as a class that needs to be constructed and then have its parseFromString() method called, is an unfortunate historical artifact. If we were designing this functionality today it would be a standalone function. For parsing HTML, the modern alternative is Document.parseHTMLUnsafe() .

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes .

[Exposed=Window]
interface DOMParser {
  constructor();
  [NewObject] Document parseFromString((TrustedHTML or DOMString) string, DOMParserSupportedType type);
};
enum DOMParserSupportedType {
  "text/html",
  "text/xml",
  "application/xml",
  "application/xhtml+xml",
  "image/svg+xml"
};

The new DOMParser() constructor steps are to do nothing.

The parseFromString( string , type ) method steps are:

  1. Let compliantString be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , string , " DOMParser parseFromString ", and " script ".

  2. Let document be a new Document , whose content type is type and URL is this 's relevant global object 's associated Document 's URL .

    The document's encoding will be left as its default, of UTF-8 . In particular, any XML declarations or meta elements found while parsing compliantString will have no effect.

  3. Switch on type :

    " text/html "
    1. Parse HTML from a string given document and compliantString .

    Since document does not have a browsing context , scripting is disabled .

    Otherwise
    1. Create an XML parser parser , associated with document , and with XML scripting support disabled .

    2. Parse compliantString using parser .

    3. If the previous step resulted in an XML well-formedness or XML namespace well-formedness error, then:

      1. Assert : document has no child nodes.

      2. Let root be the result of creating an element given document , " parsererror ", and " http://www.mozilla.org/newlayout/xml/parsererror.xml ".

      3. Optionally, add attributes or children to root to describe the nature of the parsing error.

      4. Append root to document .

  4. Return document .

To parse HTML from a string , given a Document document and a string html :

  1. Set document 's type to " html ".

  2. Create an HTML parser parser , associated with document .

  3. Place html into the input stream for parser . The encoding confidence is irrelevant .

  4. Start parser and let it run until it has consumed all the characters just inserted into the input stream.

    This might mutate the document's mode .

8.5.2 Unsafe HTML parsing methods

element . setHTMLUnsafe ( html , options )

Parses html using the HTML parser, parser with options options , and replaces the children of element with the result. element provides context for the HTML parser.

shadowRoot . setHTMLUnsafe ( html , options )

Parses html using the HTML parser, parser with options options , and replaces the children of shadowRoot with the result. shadowRoot 's host provides context for the HTML parser.

doc = Document. parseHTMLUnsafe ( html , options )

Parses html using the HTML parser, parser with options options , and returns the resulting Document .

Note that script elements are not evaluated during parsing, and the resulting document's encoding will always be UTF-8 . The document's URL will be about:blank .

These methods perform no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes .

Element 's setHTMLUnsafe( html , options ) method steps are:

  1. Let compliantHTML be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , html , " Element setHTMLUnsafe ", and " script ".

  2. Let target be this 's template contents if this is a template element; otherwise this .

  3. Unsafely set Set and filter HTML given target , this , and compliantHTML . , options , and false.

ShadowRoot 's setHTMLUnsafe( html , options ) method steps are:

  1. Let compliantHTML be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , html , " ShadowRoot setHTMLUnsafe ", and " script ".

  2. Unsafely set Set and filter HTML given this , , this 's shadow host , and compliantHTML . , options , and false.

To unsafely set HTML , given an Element or DocumentFragment target , an Element 's setHTML( contextElement html , and a string html : options ) method steps are:

  1. Let newChildren target be the result of the this 's template contents if this is a template element; otherwise this .

  2. Set and filter HTML fragment parsing algorithm given contextElement target , this , html , options , and true.

Let fragment be a new DocumentFragment ShadowRoot whose node document is contextElement 's node document . For each node in setHTML( newChildren html , append node options to fragment . ) method steps are:

  1. Replace all Set and filter HTML with given this , this 's shadow host , fragment within html , target . options , and true.


The static parseHTMLUnsafe( html , options ) method steps are:

  1. Let compliantHTML be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , html , " Document parseHTMLUnsafe ", and " script ".

  2. Let document be a new Document , whose content type is " text/html ".

    Since document does not have a browsing context , scripting is disabled .

  3. Set document 's allow declarative shadow roots to true.

  4. Parse HTML from a string given document and compliantHTML .

  5. Let sanitizer be the result of calling get a sanitizer instance from options with options and false.

  6. Call sanitize on document with sanitizer and false.

  7. Return document .

The static parseHTML( html , options ) method steps are:

  1. Let document be a new Document , whose content type is " text/html ".

    Since document does not have a browsing context , scripting is disabled .

  2. Set document 's allow declarative shadow roots to true.

  3. Parse HTML from a string given document and html .

  4. Let sanitizer be the result of calling get a sanitizer instance from options with options and true.

  5. Call sanitize on document with sanitizer and true.

  6. Return document .

8.5.3 Safe HTML parsing methods

element . setHTML ( html , options )
shadowRoot . setHTML ( html , options )

Parses html using the HTML parser with options options , and replaces the children of the element or shadow root with the result, which is then sanitized.

doc = Document . parseHTML ( html , options )

Parses html using the HTML parser with options options , and returns a new Document containing the result, which is then sanitized.

8.5.4 HTML serialization methods

html = element . getHTML ({ serializableShadowRoots , shadowRoots })

Returns the result of serializing element to HTML. Shadow roots within element are serialized according to the provided options:

If neither option is provided, then no shadow roots are serialized.

html = shadowRoot . getHTML ({ serializableShadowRoots , shadowRoots })

Returns the result of serializing shadowRoot to HTML, using its shadow host as the context element. Shadow roots within shadowRoot are serialized according to the provided options, as above.

Element 's getHTML( options ) method steps are to return the result of HTML fragment serialization algorithm with this , options [" serializableShadowRoots "], and options [" shadowRoots "].

ShadowRoot 's getHTML( options ) method steps are to return the result of HTML fragment serialization algorithm with this , options [" serializableShadowRoots "], and options [" shadowRoots "].

8.5.4 8.5.5 The innerHTML property

The innerHTML property has a number of outstanding issues in the DOM Parsing and Serialization issue tracker , documenting various problems with its specification.

element . innerHTML

Returns a fragment of HTML or XML that represents the element's contents.

In the case of an XML document, throws an " InvalidStateError " DOMException if the element cannot be serialized to XML.

element . innerHTML = value

Replaces the contents of the element with nodes parsed from the given string.

In the case of an XML document, throws a " SyntaxError " DOMException if the given string is not well-formed.

shadowRoot . innerHTML

Returns a fragment of HTML that represents the shadow roots's contents.

shadowRoot . innerHTML = value

Replaces the contents of the shadow root with nodes parsed from the given string.

These properties' setters perform no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes .

The fragment serializing algorithm steps , given an Element , Document , or DocumentFragment node and a boolean require well-formed , are:

  1. Let context document be node 's node document .

  2. If context document is an HTML document , return the result of HTML fragment serialization algorithm with node , false, and « ».

  3. Return the XML serialization of node given require well-formed .

The fragment parsing algorithm steps , given an Element context , a string markup , and an optional parser scripting mode scriptingMode (default Inert ), are:

  1. Assert : scriptingMode is either Inert or Fragment .

  2. Let newChildren be null.

  3. If context 's node document is an XML document , then set newChildren to the result of invoking the XML fragment parsing algorithm given context and markup .

  4. Otherwise, set newChildren to the result of invoking the HTML fragment parsing algorithm given context , markup , false, and scriptingMode .

  5. Let fragment be a new DocumentFragment whose node document is context 's node document .

  6. For each node of newChildren , in tree order : append node to fragment .

    This ensures the node document for the new nodes is correct.

  7. Return fragment .

Element 's innerHTML getter steps are to return the result of running fragment serializing algorithm steps with this and true.

ShadowRoot 's innerHTML getter steps are to return the result of running fragment serializing algorithm steps with this and true.

Element 's innerHTML setter steps are:

  1. Let compliantString be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , the given value, " Element innerHTML ", and " script ".

  2. Let context be this .

  3. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString .

  4. If context is a template element, then set context to the template element's template contents (a DocumentFragment ).

    Setting innerHTML on a template element will replace all the nodes in its template contents rather than its children .

  5. Replace all with fragment within context .

ShadowRoot 's innerHTML setter steps are:

  1. Let compliantString be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , the given value, " ShadowRoot innerHTML ", and " script ".

  2. Let context be this 's host .

  3. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString .

  4. Replace all with fragment within this .

8.5.5 8.5.6 The outerHTML property

The outerHTML property has a number of outstanding issues in the DOM Parsing and Serialization issue tracker , documenting various problems with its specification.

element . outerHTML

Returns a fragment of HTML or XML that represents the element and its contents.

In the case of an XML document, throws an " InvalidStateError " DOMException if the element cannot be serialized to XML.

element . outerHTML = value

Replaces the element with nodes parsed from the given string.

In the case of an XML document, throws a " SyntaxError " DOMException if the given string is not well-formed.

Throws a " NoModificationAllowedError " DOMException if the parent of the element is a Document .

This property's setter performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes .

Element 's outerHTML getter steps are:

  1. Let element be a fictional node whose only child is this .

  2. Return the result of running fragment serializing algorithm steps with element and true.

Element 's outerHTML setter steps are:

  1. Let compliantString be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , the given value, " Element outerHTML ", and " script ".

  2. Let parent be this 's parent .

  3. If parent is null, return. There would be no way to obtain a reference to the nodes created even if the remaining steps were run.

  4. If parent is a Document , throw a " NoModificationAllowedError " DOMException .

  5. If parent is a DocumentFragment , set parent to the result of creating an element given this 's node document , " body ", and the HTML namespace .

  6. Let fragment be the result of invoking the fragment parsing algorithm steps given parent and compliantString .

  7. Replace this with fragment within this 's parent .

8.5.6 8.5.7 The insertAdjacentHTML() method

The insertAdjacentHTML() method has a number of outstanding issues in the DOM Parsing and Serialization issue tracker , documenting various problems with its specification.

element . insertAdjacentHTML ( position , string )

Parses string as HTML or XML and inserts the resulting nodes into the tree in the position given by the position argument, as follows:

" beforebegin "
Before the element itself (i.e., after element 's previous sibling)
" afterbegin "
Just inside the element, before its first child.
" beforeend "
Just inside the element, after its last child.
" afterend "
After the element itself (i.e., before element 's next sibling)

Throws a " SyntaxError " DOMException if the arguments have invalid values (e.g., in the case of an XML document , if the given string is not well-formed).

Throws a " NoModificationAllowedError " DOMException if the given position isn't possible (e.g. inserting elements after the root element of a Document ).

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes .

Element 's insertAdjacentHTML( position , string ) method steps are:

  1. Let compliantString be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , string , " Element insertAdjacentHTML ", and " script ".

  2. Let context be null.

  3. Use the first matching item from this list:

    If position is an ASCII case-insensitive match for the string " beforebegin "
    If position is an ASCII case-insensitive match for the string " afterend "
    1. Set context to this 's parent .

    2. If context is null or a Document , throw a " NoModificationAllowedError " DOMException .

    If position is an ASCII case-insensitive match for the string " afterbegin "
    If position is an ASCII case-insensitive match for the string " beforeend "
    Set context to this .
    Otherwise

    Throw a " SyntaxError " DOMException .

  4. If context is not an Element or all of the following are true:

    then set context to the result of creating an element given this 's node document , " body ", and the HTML namespace .

  5. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString .

  6. Use the first matching item from this list:
    If position is an ASCII case-insensitive match for the string " beforebegin "

    Insert fragment into this 's parent before this .

    If position is an ASCII case-insensitive match for the string " afterbegin "

    Insert fragment into this before its first child .

    If position is an ASCII case-insensitive match for the string " beforeend "

    Append fragment to this .

    If position is an ASCII case-insensitive match for the string " afterend "

    Insert fragment into this 's parent before this 's next sibling .

As with other direct Node -manipulation APIs (and unlike innerHTML ), insertAdjacentHTML() does not include any special handling for template elements. In most cases you will want to use templateEl. content . insertAdjacentHTML() instead of directly manipulating the child nodes of a template element.

8.5.7 8.5.8 The createContextualFragment() method

The createContextualFragment() method has a number of outstanding issues in the DOM Parsing and Serialization issue tracker , documenting various problems with its specification.

docFragment = range . createContextualFragment ( string )

Returns a DocumentFragment created from the markup string string using range 's start node as the context in which fragment is parsed.

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes .

partial interface Range {
  [CEReactions, NewObject] DocumentFragment createContextualFragment((TrustedHTML or DOMString) string);
};

Range 's createContextualFragment( string ) method steps are:

  1. Let compliantString be the result of invoking the get trusted type compliant string algorithm with TrustedHTML , this 's relevant global object , string , " Range createContextualFragment ", and " script ".

  2. Let node be this 's start node .

  3. Let element be null.

  4. If node implements Element , set element to node .

  5. Otherwise, if node implements Text or Comment , set element to node 's parent element .

  6. If element is null or all of the following are true:

    then set element to the result of creating an element given this 's node document , " body ", and the HTML namespace .

  7. Return the result of invoking the fragment parsing algorithm steps with element , compliantString , and Fragment .

8.5.8 8.5.9 The XMLSerializer interface

The XMLSerializer interface has a number of outstanding issues in the DOM Parsing and Serialization issue tracker , documenting various problems with its specification. The remainder of DOM Parsing and Serialization will be gradually upstreamed to this specification.

xmlSerializer = new XMLSerializer ()

Constructs a new XMLSerializer object.

string = xmlSerializer . serializeToString ( root )

Returns the result of serializing root to XML.

Throws an " InvalidStateError " DOMException if root cannot be serialized to XML.

The design of XMLSerializer , as a class that needs to be constructed and then have its serializeToString() method called, is an unfortunate historical artifact. If we were designing this functionality today it would be a standalone function.

[Exposed=Window]
interface XMLSerializer {
  constructor();
  DOMString serializeToString(Node root);
};

The new XMLSerializer() constructor steps are to do nothing.

The serializeToString( root ) method steps are:

  1. Return the XML serialization of root given false.

8.6 HTML sanitization

8.6.1 Introduction

This section is non-normative.

Web applications often need to work with strings of HTML on the client side, perhaps as part of a client-side templating solution, or perhaps as part of rendering user-generated content. It is difficult to do so in a safe way. The naive approach of joining strings together and stuffing them into an element's innerHTML is fraught with risk, as it can cause script execution in a number of unexpected ways.

Libraries like DOMPurify attempt to manage this problem by carefully parsing and sanitizing strings before insertion, by constructing a DOM and filtering its members through an allow-list. This has proven to be a fragile approach, as the parsing APIs exposed to the web don't always map in reasonable ways to the browser's behavior when actually rendering a string as HTML in the "real" DOM. Moreover, the libraries need to keep on top of browsers' changing behavior over time; things that once were safe may turn into time-bombs based on new platform-level features.

The browser has a fairly good idea of when it is going to execute code. We can improve upon user-space libraries by teaching the browser how to render HTML from an arbitrary string in a safe manner, and do so in a way that is much more likely to be maintained and updated along with the browser's own changing parser implementation. The APIs in this section aim to do just that.

The goals of these APIs are:

These APIs offer functionality to parse a string containing HTML into a DOM tree, and to filter the resulting tree according to a user-supplied configuration. The methods come in two main flavors:

Safe and unsafe

The "safe" methods will not generate any markup that executes script. That is, they are intended to be safe from XSS. The "unsafe" methods will parse and filter based on the provided configuration, but do not have the same safety guarantees by default.

Context

Methods are defined on Element and ShadowRoot and will replace these node's children, and are largely analogous to innerHTML . There are also static methods on the Document , which parse an entire document and are largely analogous to parseFromString() .

8.6.2 The Sanitizer interface

[Exposed=Window]
interface Sanitizer {
  constructor(optional (SanitizerConfig or SanitizerPresets) configuration = "default");
  // Query configuration:
  SanitizerConfig get();
  // Modify a Sanitizer's lists and fields:
  boolean allowElement(SanitizerElementWithAttributes element);
  boolean removeElement(SanitizerElement element);
  boolean replaceElementWithChildren(SanitizerElement element);
  boolean allowProcessingInstruction(SanitizerProcessingInstruction pi);
  boolean removeProcessingInstruction(SanitizerProcessingInstruction pi);
  boolean allowAttribute(SanitizerAttribute attribute);
  boolean removeAttribute(SanitizerAttribute attribute);
  boolean setComments(boolean allow);
  boolean setDataAttributes(boolean allow);
  // Remove markup that executes script.
  boolean removeUnsafe();
};
config = sanitizer . get ()

Returns a copy of the sanitizer's configuration .

sanitizer . allowElement ( element )

Ensures that the sanitizer configuration allows the specified element.

sanitizer . removeElement ( element )

Ensures that the sanitizer configuration blocks the specified element.

sanitizer . replaceElementWithChildren ( element )

Configures the sanitizer to remove the specified element but keep its child nodes.

sanitizer . allowAttribute ( attribute )

Configures the sanitizer to allow the specified attribute globally.

sanitizer . removeAttribute ( attribute )

Configures the sanitizer to block the specified attribute globally.

sanitizer . allowProcessingInstruction ( pi )

Configures the sanitizer to allow the specified processing instruction.

sanitizer . removeProcessingInstruction ( pi )

Configures the sanitizer to block the specified processing instruction.

sanitizer . setComments ( allow )

Sets whether the sanitizer preserves comments.

sanitizer . setDataAttributes ( allow )

Sets whether the sanitizer preserves custom data attributes (e.g., data-* ).

sanitizer . removeUnsafe ()

Modifies the configuration to automatically remove elements and attributes that are considered unsafe.

A Sanitizer has an associated configuration (a SanitizerConfig ).

The new Sanitizer( configuration ) constructor steps are:

  1. If configuration is a SanitizerPresets string , then:

    1. Assert : configuration is " default ".

    2. Set configuration to the built-in safe default configuration .

  2. If set a configuration configuration with true and this is false, then throw a TypeError .

The allowProcessingInstruction( pi ) method steps are:

  1. Let configuration be this 's configuration .

  2. Set pi to the result of canonicalize a sanitizer processing instruction with pi .

  3. If configuration [" processingInstructions "] exists , then:

    1. If configuration [" processingInstructions "] contains pi , then return false.

    2. Append pi to configuration [" processingInstructions "].

    3. Return true.

  4. Otherwise:

    1. If configuration [" removeProcessingInstructions "] contains pi , then:

      1. Remove pi from configuration [" removeProcessingInstructions "].

      2. Return true.

    2. Return false.

The removeProcessingInstruction( pi ) method steps are:

  1. Let configuration be this 's configuration .

  2. Set pi to the result of canonicalize a sanitizer processing instruction with pi .

  3. If configuration [" processingInstructions "] exists , then:

    1. If configuration [" processingInstructions "] contains pi , then:

      1. Remove pi from configuration [" processingInstructions "].

      2. Return true.

    2. Return false.

  4. Otherwise:

    1. If configuration [" removeProcessingInstructions "] contains pi , then return false.

    2. Append pi to configuration [" removeProcessingInstructions "].

    3. Return true.

To set a configuration , given a dictionary configuration , a boolean allowCommentsPIsAndDataAttributes , and a Sanitizer sanitizer :

  1. Canonicalize the configuration configuration with allowCommentsPIsAndDataAttributes .

  2. If configuration is not valid , then return false.

  3. Set sanitizer 's configuration to configuration .

  4. Return true.

To canonicalize the configuration SanitizerConfig configuration with a boolean allowCommentsPIsAndDataAttributes :

  1. For each member of configuration that is a list of strings:

    1. Replace each string in member with the result of canonicalizing it using the appropriate algorithm (e.g., canonicalize a sanitizer element or canonicalize a sanitizer attribute ).

  2. If configuration [" elements "] exists , then:

    1. For each element in configuration [" elements "]:

      1. If element [" attributes "] exists , replace each attribute with the result of canonicalize a sanitizer attribute .

      2. If element [" removeAttributes "] exists , replace each attribute with the result of canonicalize a sanitizer attribute .

  3. If neither configuration [" elements "] nor configuration [" removeElements "] exists , then set configuration [" removeElements "] to an empty list.

  4. If neither configuration [" attributes "] nor configuration [" removeAttributes "] exists , then set configuration [" removeAttributes "] to an empty list.

  5. If neither configuration [" processingInstructions "] nor configuration [" removeProcessingInstructions "] exists , then:

    1. If allowCommentsPIsAndDataAttributes is true, then set configuration [" removeProcessingInstructions "] to an empty list.

    2. Otherwise, set configuration [" processingInstructions "] to an empty list.

  6. If configuration [" comments "] does not exist , set it to allowCommentsPIsAndDataAttributes .

  7. If configuration [" dataAttributes "] does not exist , set it to allowCommentsPIsAndDataAttributes .

In order to canonicalize a sanitizer element element , run the following steps:

  1. If element is a string, then return a new SanitizerElementNamespace dictionary with its name member set to element and its _namespace member set to the HTML namespace .

  2. Return element .

In order to canonicalize a sanitizer attribute attribute , run the following steps:

  1. If attribute is a string, then return a new SanitizerAttributeNamespace dictionary with its name member set to attribute and its _namespace member set to null.

  2. Return attribute .

In order to canonicalize a sanitizer processing instruction pi , run the following steps:

  1. If pi is a string, then set pi to a new SanitizerProcessingInstruction dictionary with its target member set to pi .

  2. Return pi .

8.6.3 Sanitizer configuration

dictionary SanitizerElementNamespace {
  required DOMString name;
  DOMString? _namespace = "http://www.w3.org/1999/xhtml";
};
// Used by "elements"
dictionary SanitizerElementNamespaceWithAttributes : SanitizerElementNamespace {
  sequence<SanitizerAttribute> attributes;
  sequence<SanitizerAttribute> removeAttributes;
};
typedef (DOMString or SanitizerElementNamespace) SanitizerElement;
typedef (DOMString or SanitizerElementNamespaceWithAttributes) SanitizerElementWithAttributes;
dictionary SanitizerProcessingInstruction {
  required DOMString target;
};
typedef (DOMString or SanitizerProcessingInstruction) SanitizerPI;
dictionary SanitizerAttributeNamespace {
  required DOMString name;
  DOMString? _namespace = null;
};
typedef (DOMString or SanitizerAttributeNamespace) SanitizerAttribute;
dictionary SanitizerConfig {
  sequence<SanitizerElementWithAttributes> elements;
  sequence<SanitizerElement> removeElements;
  sequence<SanitizerElement> replaceWithChildrenElements;
  sequence<SanitizerProcessingInstruction> processingInstructions;
  sequence<SanitizerProcessingInstruction> removeProcessingInstructions;
  sequence<SanitizerAttribute> attributes;
  sequence<SanitizerAttribute> removeAttributes;
  boolean comments;
  boolean dataAttributes;
};
8.6.3.1 Configuration invariants

Configurations can and ought to be modified by developers to suit their purposes. Options are to write a new SanitizerConfig dictionary from scratch, to modify an existing Sanitizer 's configuration by using the modifier methods, or to get() an existing Sanitizer 's configuration as a dictionary and modify the dictionary and then create a new Sanitizer with it.

An empty configuration allows everything (when called with the "unsafe" methods like setHTMLUnsafe() ). A configuration " default " contains a built-in safe default configuration . Note that "safe" and "unsafe" sanitizer methods have different defaults.

Not all configuration dictionaries are valid. A valid configuration avoids redundancy (like specifying the same element to be allowed twice) and contradictions (like specifying an element to be both removed and allowed.)

Several conditions need to hold for a configuration to be valid:

The elements element allow-list can also specify allowing or removing attributes for a given element. This is meant to mirror this standard's structure, which knows both global attributes as well as local attributes that apply to a specific element. Global and local attributes can be mixed, but note that ambiguous configurations where a particular attribute would be allowed by one list and forbidden by another, are generally invalid.

global attributes global removeAttributes
local attributes An attribute is allowed if it matches either list. No duplicates are allowed. An attribute is only allowed if it's in the local allow list. No duplicate entries between global remove and local allow lists are allowed. Note that the global remove list has no function for this particular element, but may well apply to other elements that do not have a local allow list.
local removeAttributes An attribute is allowed if it's in the global allow-list, but not in the local remove-list. Local remove must be a subset of the global allow lists. An attribute is allowed if it is in neither list. No duplicate entries between global remove and local remove lists are allowed.

Please note the asymmetry where mostly no duplicates between global and per-element lists are permitted, but in the case of a global allow-list and a per-element remove-list the latter must be a subset of the former. An excerpt of the table above, only focusing on duplicates, is as follows:

global attributes global removeAttributes
local attributes No duplicates are allowed. No duplicates are allowed.
local removeAttributes Local remove must be a subset of the global allow lists. No duplicates are allowed.

The dataAttributes setting allows custom data attributes . The rules above easily extends to custom data attributes if one considers dataAttributes to be an allow-list:

global attributes and dataAttributes set
local attributes All custom data attributes are allowed. No custom data attributes may be listed in any allow-list, as that would mean a duplicate entry.
local removeAttributes A custom data attribute is allowed, unless it's listed in the local remove-list. No custom data attribute may be listed in the global allow-list, as that would mean a duplicate entry.

Putting these rules in words:

8.6.4 Processing model

The get() method steps are:

Outside of the get() method, the order of the Sanitizer 's elements and attributes is unobservable. By explicitly sorting the result of this method, we give implementations the opportunity to optimize by, for example, using unordered sets internally.

  1. Let config be this 's configuration .

  2. Assert : config is valid .

  3. If config [" elements "] exists , then:

    1. For any element of config [" elements "]:

      1. If element [" attributes "] exists , then set element [" attributes "] to the result of sort in ascending order element [" attributes "], with compare sanitizer items .

      2. If element [" removeAttributes "] exists , then set element [" removeAttributes "] to the result of sort in ascending order element [" removeAttributes "], with compare sanitizer items .

    2. Set config [" elements "] to the result of sort in ascending order config [" elements "], with compare sanitizer items .

  4. Otherwise:

    1. Set config [" removeElements "] to the result of sort in ascending order config [" removeElements "], with compare sanitizer items .

  5. If config [" replaceWithChildrenElements "] exists , then set config [" replaceWithChildrenElements "] to the result of sort in ascending order config [" replaceWithChildrenElements "], with compare sanitizer items .

  6. If config [" processingInstructions "] exists , then set config [" processingInstructions "] to the result of sort in ascending order config [" processingInstructions "], with piA [" target "] being code unit less than piB [" target "].

  7. Otherwise:

    1. Set config [" removeProcessingInstructions "] to the result of sorting config [" removeProcessingInstructions "], with piA [" target "] being code unit less than piB [" target "].

  8. If config [" attributes "] exists , then set config [" attributes "] to the result of sorting config [" attributes "] given compare sanitizer items .

  9. Otherwise:

    1. Set config [" removeAttributes "] to the result of sorting config [" removeAttributes "] given compare sanitizer items .

  10. Return config .

To compare sanitizer items itemA and itemB :

  1. Let namespaceA be itemA [" _namespace "].

  2. Let namespaceB be itemB [" _namespace "].

  3. If namespaceA is null, then:

    1. If namespaceB is not null, then return true.

  4. Otherwise:

    1. If namespaceB member is null, then return false.

    2. If namespaceA is code unit less than namespaceB , then return true.

    3. If namespaceA is not namespaceB , then return false.

  5. If itemA [" name "] is code unit less than itemA [" name "], return true.

  6. Return false.

The allowElement( element ) method steps are:

  1. Let configuration be this 's configuration .

  2. Assert : configuration is valid .

  3. Set element to the result of canonicalize a sanitizer element with attributes with element .

  4. If configuration [" elements "] exists , then:

    1. Let modified be the result of removing element from configuration [" replaceWithChildrenElements "].

    2. If configuration [" attributes "] exists , then:

      1. If element [" attributes "] exists , then:

        1. Set element [" attributes "] to the result of remove duplicates from element [" attributes "].

        2. Set element [" attributes "] to the set/difference of element [" attributes "] and configuration [" attributes "].

        3. If configuration [" dataAttributes "] is true, then remove all items item from element [" attributes "] where item is a custom data attribute .

      2. If element [" removeAttributes "] exists , then:

        1. Set element [" removeAttributes "] to the result of remove duplicates from element [" removeAttributes "].

        2. Set element [" removeAttributes "] to the intersection of element [" removeAttributes "] and configuration [" attributes "].

    3. Otherwise:

      1. If element [" attributes "] exists , then:

        1. Set element [" attributes "] to the result of remove duplicates from element [" attributes "].

        2. Set element [" attributes "] to the set/difference of element [" attributes "] and element [" removeAttributes "] (or an empty list if it does not exist).

        3. Remove element [" removeAttributes "].

        4. Set element [" attributes "] to the set/difference of element [" attributes "] and configuration [" removeAttributes "].

      2. If element [" removeAttributes "] exists , then:

        1. Set element [" removeAttributes "] to the result of remove duplicates from element [" removeAttributes "].

        2. Set element [" removeAttributes "] to the set/difference of element [" removeAttributes "] and configuration [" removeAttributes "].

    4. If configuration [" elements "] does not contain element , then:

      1. Append element to configuration [" elements "].

      2. Return true.

    5. Let current element be the item in configuration [" elements "] whose name member is element 's name member and whose _namespace member is element 's _namespace member.

    6. If element is equal to current element , then return modified .

    7. Remove element from configuration [" elements "].

    8. Append element to configuration [" elements "].

    9. Return true.

  5. Otherwise:

    1. If element [" attributes "] exists or element [" removeAttributes "] (or an empty list if it does not exist) is not empty, then return false.

    2. Let modified be the result of removing element from configuration [" replaceWithChildrenElements "].

    3. If configuration [" removeElements "] does not contain element , then return modified .

    4. Remove element from configuration [" removeElements "].

    5. Return true.

The removeElement( element ) method steps are to return the result of removing element from this 's configuration .

The replaceElementWithChildren( element ) method steps are:

  1. Let configuration be this 's configuration .

  2. Assert : configuration is valid .

  3. Set element to the result of canonicalize a sanitizer element with element .

  4. If the built-in non-replaceable elements list contains element , then return false.

  5. Let modified be the result of removing element from configuration [" elements "].

  6. If removing element from configuration [" removeElements "] is true, then set modified to true.

  7. If configuration [" replaceWithChildrenElements "] does not sanitizer config list contains element , then:

    1. Append element to configuration [" replaceWithChildrenElements "].

    2. Return true.

  8. Return modified .

The allowAttribute( attribute ) method steps are:

  1. Let configuration be this 's configuration .

  2. Assert : configuration is valid .

  3. Set attribute to the result of canonicalize a sanitizer attribute with attribute .

  4. If configuration [" attributes "] exists , then:

    1. If configuration [" dataAttributes "] is true and attribute is a custom data attribute , then return false.

    2. If configuration [" attributes "] contains attribute , then return false.

    3. If configuration [" elements "] exists , then:

      1. For each element in configuration [" elements "]:

        1. If element [" attributes "] (or an empty list if it does not exist) sanitizer config list contains attribute , then remove attribute from element [" attributes "].

    4. Append attribute to configuration [" attributes "].

    5. Return true.

  5. Otherwise:

    1. If configuration [" removeAttributes "] does not contain attribute , then return false.

    2. Remove attribute from configuration [" removeAttributes "].

    3. Return true.

The removeAttribute( attribute ) method steps are to return the result of remove an attribute with attribute and this 's configuration .

The setComments( allow ) method steps are:

  1. Let configuration be this 's configuration .

  2. Assert : configuration is valid .

  3. If configuration [" comments "] exists and is equal to allow , then return false.

  4. Set configuration [" comments "] to allow .

  5. Return true.

The setDataAttributes( allow ) method steps are:

  1. Let configuration be this 's configuration .

  2. Assert : configuration is valid .

  3. If configuration [" dataAttributes "] exists and is equal to allow , then return false.

  4. If allow is false and configuration [" attributes "] exists , then:

    1. For each element in configuration [" elements "] (or an empty list if it does not exist):

      1. Remove all items item from element [" attributes "] (or an empty list if it does not exist) where item is a custom data attribute .

    2. Remove all items item from configuration [" attributes "] where item is a custom data attribute .

  5. Set configuration [" dataAttributes "] to allow .

  6. Return true.

The removeUnsafe() method steps are to update this 's configuration with the result of remove unsafe from this 's configuration .

8.6.5 Sanitization algorithms

To set and filter HTML , given an Element or DocumentFragment target , an Element contextElement , a string html , a dictionary options , and a boolean safe :

  1. If all of the following are true:

    then return.

  2. Let sanitizer be the result of calling getting a sanitizer from options given safe .

  3. Let newChildren be the result of parsing a fragment given contextElement , html , and true.

  4. Let fragment be a new DocumentFragment whose node document is contextElement 's node document .

  5. For each node in newChildren , append node to fragment .

  6. Sanitize fragment given sanitizer and safe .

  7. Replace all with fragment within target .

To get a sanitizer instance from options from a dictionary options with a boolean safe :

  1. Let sanitizerSpec be " default ".

  2. If options [" sanitizer "] exists , then set sanitizerSpec to options [" sanitizer "].

  3. Assert : sanitizerSpec is either a Sanitizer instance, a SanitizerPresets member, or a SanitizerConfig dictionary.

  4. If sanitizerSpec is a string, then:

    1. Assert : sanitizerSpec is " default ".

    2. Set sanitizerSpec to the built-in safe default configuration .

  5. If sanitizerSpec is a dictionary, then:

    1. Let sanitizer be a new Sanitizer instance.

    2. Let inverseSafe be true if safe is false; false otherwise.

    3. If the result of setting a configuration sanitizerSpec with ( inverseSafe ) and sanitizer is false, then throw a TypeError .

    4. Set sanitizerSpec to sanitizer .

  6. Return sanitizerSpec .

To sanitize a node node with a Sanitizer sanitizer and a boolean safe :

  1. Let configuration be sanitizer 's configuration .

  2. Assert : configuration is valid .

  3. If safe is true, then set configuration to the result of calling remove unsafe on configuration .

  4. Sanitize node given configuration and safe .

To perform the inner sanitize steps on a Node node , given a SanitizerConfig configuration , and a boolean handleJavascriptNavigationUrls :

  1. For each child of node 's children :

    1. Assert : child is a Text , Comment , Element , ProcessingInstruction , or DocumentType node.

    2. If child is a DocumentType node, then continue .

    3. If child is a Text node, then continue .

    4. If child is a Comment node, then:

      1. If configuration [" comments "] is not true, then remove child .

    5. If child is a ProcessingInstruction node, then:

      1. Let piTarget be child 's target .

      2. If configuration [" processingInstructions "] exists , then:

        1. If configuration [" processingInstructions "] does not sanitizer config list contains piTarget , then remove child .

      3. Otherwise:

        1. If configuration [" removeProcessingInstructions "] sanitizer config list contains piTarget , then remove child .

    6. Otherwise:

      1. Let elementName be a SanitizerElementNamespace with child 's local name and namespace .

      2. If configuration [" replaceWithChildrenElements "] exists and configuration [" replaceWithChildrenElements "] sanitizer config list contains elementName , then:

        1. Assert : node is not a Document .

        2. Sanitize child given configuration and handleJavascriptNavigationUrls .

        3. Replace all with child 's children within child .

        4. Continue .

      3. If configuration [" elements "] exists , then:

        1. If configuration [" elements "] does not contain elementName , then remove child and continue .

      4. Otherwise:

        1. If configuration [" removeElements "] contains elementName , then remove child and continue .

      5. If elementName is a template element in the HTML namespace , then sanitize child 's template contents given configuration and handleJavascriptNavigationUrls .

      6. If child is a shadow host , then sanitize child 's shadow root given configuration and handleJavascriptNavigationUrls .

      7. Let elementWithLocalAttributes be null.

      8. If configuration [" elements "] exists and configuration [" elements "] contains elementName , then set elementWithLocalAttributes to configuration [" elements "][ elementName ].

      9. For each attribute in child 's attribute list :

        1. Let attrName be a SanitizerAttributeNamespace with attribute 's local name and namespace .

        2. If elementWithLocalAttributes [" removeAttributes "] exists and elementWithLocalAttributes [" removeAttributes "] sanitizer config list contains attrName , then remove an attribute attribute .

        3. Otherwise, if configuration [" attributes "] exists , then:

          1. If configuration [" attributes "] does not contain attrName and elementWithLocalAttributes [" attributes "] does not sanitizer config list contains attrName , and if " data- " is not a prefix of attribute 's local name or attribute 's namespace is not null or configuration [" dataAttributes "] is not true, then remove an attribute attribute .

        4. Otherwise:

          1. If elementWithLocalAttributes [" attributes "] exists and elementWithLocalAttributes [" attributes "] does not sanitizer config list contains attrName , then remove attribute from configuration .

          2. Otherwise, if configuration [" removeAttributes "] contains attrName , then remove attribute from configuration .

        5. If handleJavascriptNavigationUrls is true, then:

          1. If the pair ( elementName , attrName ) matches an entry in the built-in navigating URL attributes list , and if attribute contains a javascript: URL , then remove an attribute attribute .

          2. If child 's namespace is the MathML Namespace , attribute 's local name is " href ", and attribute 's namespace is null or the XLink namespace , and attribute contains a javascript: URL , then remove an attribute attribute .

          3. If the built-in animating URL attributes list contains the pair ( elementName , attrName ), and attribute 's value is " href " or " xlink:href ", then remove attribute from configuration .

      10. Sanitize child given configuration and handleJavascriptNavigationUrls .

To determine whether an attribute attribute contains a javascript: URL :

  1. Let url be the result of running the basic URL parser on attribute 's value .

  2. If url is failure, then return false.

  3. Return whether url 's scheme is " javascript ".

8.6.6 Sanitization constants

The built-in safe baseline configuration is a SanitizerConfig with its removeElements corresponding to the following table:

Name Namespace
embed HTML
frame HTML
iframe HTML
object HTML
script HTML
script SVG
use SVG

and the following removeAttributes list:

The built-in safe default configuration is a SanitizerConfig with its elements list corresponding to the following table:

Element Namespace Allowed Attributes
math MathML
merror MathML
mfrac MathML
mi MathML
mmultiscripts MathML
mn MathML
mo MathML fence , form , largeop , lspace , maxsize , minsize , movablelimits , rspace , separator , stretchy , symmetric
mover MathML accent
mpadded MathML depth , height , lspace , voffset , width
mphantom MathML
mprescripts MathML
mroot MathML
mrow MathML
ms MathML
mspace MathML depth , height , width
msqrt MathML
mstyle MathML
msub MathML
msubsup MathML
msup MathML
mtable MathML
mtd MathML columnspan , rowspan
mtext MathML
mtr MathML
munder MathML accentunder
munderover MathML accent , accentunder
semantics MathML
a HTML href , hreflang , type
abbr HTML
address HTML
article HTML
aside HTML
b HTML
bdi HTML
bdo HTML
blockquote HTML cite
body HTML
br HTML
caption HTML
cite HTML
code HTML
col HTML span
colgroup HTML span
data HTML value
dd HTML
del HTML cite , datetime
dfn HTML
div HTML
dl HTML
dt HTML
em HTML
figcaption HTML
figure HTML
footer HTML
h1 HTML
h2 HTML
h3 HTML
h4 HTML
h5 HTML
h6 HTML
head HTML
header HTML
hgroup HTML
hr HTML
html HTML
i HTML
ins HTML cite , datetime
kbd HTML
li HTML value
main HTML
mark HTML
menu HTML
nav HTML
ol HTML reversed , start , type
p HTML
pre HTML
q HTML
rp HTML
rt HTML
ruby HTML
s HTML
samp HTML
search HTML
section HTML
small HTML
span HTML
strong HTML
sub HTML
sup HTML
table HTML
tbody HTML
td HTML colspan , headers , rowspan
tfoot HTML
th HTML abbr , colspan , headers , rowspan , scope
thead HTML
time HTML datetime
title HTML
tr HTML
u HTML
ul HTML
var HTML
wbr HTML
a SVG href , hreflang , type
circle SVG cx , cy , pathLength , r
defs SVG
desc SVG
ellipse SVG cx , cy , pathLength , rx , ry
foreignObject SVG height , width , x , y
g SVG
line SVG pathLength , x1 , x2 , y1 , y2
marker SVG markerHeight , markerUnits , markerWidth , orient , preserveAspectRatio , refX , refY , viewBox
metadata SVG
path SVG d , pathLength
polygon SVG pathLength , points
polyline SVG pathLength , points
rect SVG height , pathLength , rx , ry , width , x , y
svg SVG height , preserveAspectRatio , viewBox , width , x , y
text SVG dx , dy , lengthAdjust , rotate , textLength , x , y
textPath SVG lengthAdjust , method , path , side , spacing , startOffset , textLength
title SVG
tspan SVG dx , dy , lengthAdjust , rotate , textLength , x , y

The built-in navigating URL attributes list corresponds to theh following table:

Element Element Namespace Attribute Attribute Namespace
a HTML href , hreflang , type
area HTML href
base HTML href
button HTML formaction
form HTML action
input HTML formaction
a SVG href XLink namespace

The built-in animating URL attributes list corrsponds to the following table:

Element Element Namespace Attribute
animate SVG attributeName
animateTransform SVG attributeName
set SVG attributeName

To remove an element element from a SanitizerConfig configuration :

  1. Assert : configuration is valid .

  2. Set element to the result of canonicalize a sanitizer element with element .

  3. Let modified be the result of removing element from configuration [" replaceWithChildrenElements "].

  4. If configuration [" elements "] exists , then:

    1. If configuration [" elements "] contains element , then:

      1. Remove element from configuration [" elements "].

      2. Return true.

    2. Return modified .

  5. Otherwise:

    1. If configuration [" removeElements "] contains element , then return modified .

    2. Append element to configuration [" removeElements "].

    3. Return true.

To remove an attribute attribute from a SanitizerConfig configuration :

  1. Assert : configuration is valid .

  2. Set attribute to the result of canonicalize a sanitizer attribute with attribute .

  3. If configuration [" attributes "] exists , then:

    1. Let modified be the result of removing attribute from configuration [" attributes "].

    2. If configuration [" elements "] exists , then:

      1. For each element of configuration [" elements "]:

        1. If element [" attributes "] (or an empty list if it does not exist) sanitizer config list contains attribute , then:

          1. Set modified to true.

          2. Remove attribute from element [" attributes "].

        2. If element [" removeAttributes "] (or an empty list if it does not exist) sanitizer config list contains attribute , then:

          1. Assert : modified is true.

          2. Remove attribute from element [" removeAttributes "].

    3. Return modified .

  4. Otherwise:

    1. If configuration [" removeAttributes "] contains attribute , then return false.

    2. If configuration [" elements "] exists , then:

      1. For each element in configuration [" elements "]:

        1. If element [" attributes "] (or an empty list if it does not exist) sanitizer config list contains attribute , then remove attribute from element [" attributes "].

        2. If element [" removeAttributes "] (or an empty list if it does not exist) sanitizer config list contains attribute , then remove attribute from element [" removeAttributes "].

    3. Append attribute to configuration [" removeAttributes "].

    4. Return true.

To remove unsafe from a SanitizerConfig configuration :

  1. Assert : configuration is valid .

  2. Let result be false.

  3. For each element in built-in safe baseline configuration [" removeElements "]:

    1. If removing element from configuration is true, then set result to true.

  4. For each attribute in built-in safe baseline configuration [" removeAttributes "]:

    1. If removing attribute from configuration returned true, then set result to true.

  5. For each attribute that is an event handler content attribute :

    1. If removing attribute from configuration returned true, then set result to true.

  6. Return result .

To remove from sanitizer config list given an item and a list :

  1. Let removed be false.

  2. For each entry of list :

    1. If item 's name member is equal to entry 's name member and item 's _namespace member is equal to entry 's _namespace member, then:

      1. Remove entry from list .

      2. Set removed to true.

  3. Return removed .

To sanitizer config list contains , given an item item and a list list :

  1. For each entry of list :

    1. If item has a target member, and entry has a matching target member, then return true.

    2. Otherwise, if item 's name member is equal to entry 's name member and item 's _namespace member is equal to entry 's _namespace member, then return true.

  2. Return false.

To SanitizerConfig/add a name to a list list :

  1. If list sanitizer config list contains name , then return.

  2. Append name to list .

To check if a list list contains a processing instruction target given item :

  1. For each entry of list :

    1. If item 's target member is equal to entry 's target member, then return true.

  2. Return false.

To remove prcessing instruction from sanitizer config list , given an item item and a list list :

  1. Let removed be false.

  2. For each entry of list :

    1. If item 's target member is equal to entry 's target member, then:

      1. remove entry from list .

      2. Set removed to true.

  3. Return removed .

To canonicalize a sanitizer element with attributes a SanitizerElementWithAttributes element :

  1. Let result be the result of canonicalize a sanitizer element with element .

  2. If element is a dictionary, then:

    1. If element [" attributes "] exists , then:

      1. Let attributes be an empty list.

      2. For each attribute of element [" attributes "]:

        1. Append the result of canonicalize a sanitizer attribute with attribute to attributes .

      3. Set result [" attributes "] to attributes .

    2. If element [" removeAttributes "] exists , then:

      1. Let attributes be an empty list.

      2. For each attribute of element [" removeAttributes "]:

        1. Append the result of canonicalize a sanitizer attribute with attribute to attributes .

      3. Set result [" removeAttributes "] to attributes .

  3. If neither result [" attributes "] nor result [" removeAttributes "] exists , then set result [" removeAttributes "] to an empty list.

  4. Return result .

To determine whether a canonical SanitizerConfig config is valid :

It's expected that the configuration being passing in has previously been run through the canonicalize the configuration steps. We will simply assert conditions that that algorithm is guaranteed to hold.

  1. Assert : config [" elements "] exists or config [" removeElements "] exists .

  2. If config [" elements "] exists and config [" removeElements "] exists , then return false.

  3. Assert : Either config [" processingInstructions "] exists or config [" removeProcessingInstructions "] exists .

  4. If config [" processingInstructions "] exists and config [" removeProcessingInstructions "] exists , then return false.

  5. Assert : Either config [" attributes "] exists or config [" removeAttributes "] exists .

  6. If config [" attributes "] exists and config [" removeAttributes "] exists , then return false.

  7. Assert : All SanitizerElementNamespaceWithAttributes , SanitizerElementNamespace , SanitizerProcessingInstruction , and SanitizerAttributeNamespace items in config are canonical, meaning they have been run through canonicalize a sanitizer element , canonicalize a sanitizer processing instruction , or canonicalize a sanitizer attribute , as appropriate.

  8. If config [" elements "] exists :

    1. If config [" elements "] has duplicates , then return false.

  9. Otherwise:

    1. If config [" removeElements "] has duplicates , then return false.

  10. If config [" replaceWithChildrenElements "] exists and has duplicates , then return false.

  11. If config [" processingInstructions "] exists :

    1. If config [" processingInstructions "] has duplicate targets , then return false.

  12. Otherwise:

    1. If config [" removeProcessingInstructions "] has duplicate targets , then return false.

  13. If config [" attributes "] exists :

    1. If config [" attributes "] has duplicates , then return false.

  14. Otherwise:

    1. If config [" removeAttributes "] has duplicates , then return false.

  15. If config [" replaceWithChildrenElements "] exists :

    1. For each element of config [" replaceWithChildrenElements "]:

      1. If the built-in non-replaceable elements list contains element , then return false.

    2. If config [" elements "] exists :

      1. If the intersection of config [" elements "] and config [" replaceWithChildrenElements "] is not empty, then return false.

    3. Otherwise:

      1. If the intersection of config [" removeElements "] and config [" replaceWithChildrenElements "] is not empty, then return false.

  16. If config [" attributes "] exists :

    1. Assert : config [" dataAttributes "] exists .

    2. If config [" elements "] exists :

      1. For each element of config [" elements "]:

        1. If element [" attributes "] exists and element [" attributes "] has duplicates , then return false.

        2. If element [" removeAttributes "] exists and element [" removeAttributes "] has duplicates , then return false.

        3. If the intersection of config [" attributes "] and element [" attributes "] (or an empty list if it does not exist) is not empty, then return false.

        4. If element [" removeAttributes "] (or an empty list if it does not exist) is not a subset of config [" attributes "], then return false.

        5. If config [" dataAttributes "] is true and element [" attributes "] contains a custom data attribute , then return false.

    3. If config [" dataAttributes "] is true and config [" attributes "] contains a custom data attribute , then return false.

  17. Otherwise:

    1. If config [" elements "] exists :

      1. For each element of config [" elements "]:

        1. If element [" attributes "] exists and element [" removeAttributes "] exists , then return false.

        2. If element [" attributes "] exists and element [" attributes "] has duplicates , then return false.

        3. If element [" removeAttributes "] exists and element [" removeAttributes "] has duplicates , then return false.

        4. If the intersection of config [" removeAttributes "] and element [" attributes "] (or an empty list if it does not exist) is not empty, then return false.

        5. If the intersection of config [" removeAttributes "] and element [" removeAttributes "] (or an empty list if it does not exist) is not empty, then return false.

    2. If config [" dataAttributes "] exists , then return false.

  18. Return true.

A list list has duplicates if it contains two or more items that are equal.

To remove duplicates from a list list , run the following steps:

  1. Let result be an empty list.

  2. For each item of list :

    1. If result does not contain item , then append item to result .

  3. Return result .

A list list has duplicate targets if it contains two or more SanitizerProcessingInstruction items with the same target member.

The intersection of sanitizer config lists A and B containing SanitizerElement or SanitizerAttribute items is a list containing all items that are present in both A and B .

A list A is a subset of a list B if A contains everyh item in B .

To compute the difference of two lists A and B :

  1. Let result be an empty list.

  2. For each item of A :

    1. If B does not contain item , then append item to result .

  3. Return result .

Two lists A and B are equal if A is a subset of B and B is a subset of A .

The built-in non-replaceable elements list contains elements that must not be replaced with their children, as doing so can lead to re-parsing issues or an invalid node tree. It is the following list of SanitizerElementNamespace dictionaries: