diff --git a/index.bs b/index.bs
index 669eb9d..cf7aa07 100644
--- a/index.bs
+++ b/index.bs
@@ -116,7 +116,7 @@ partial interface Element {
{{Element}}'s setHTMLUnsafe(|html|, |options|?) method steps are:
1. Let |target| be |this|'s [=template contents=] if [=this=] is {{HTMLTemplateElement|template}} element; otherwise |this|.
-1. [=Unsafely set HTML=] given |target|, [=this=], |html|, and |options|.
+1. [=Set and filter HTML=] given |target|, [=this=], |html|, |options|, and `safe` set to `false`.
@@ -125,7 +125,7 @@ partial interface Element {
1. Let |target| be |this|'s [=template contents=] if [=this=] is a
{{HTMLTemplateElement|template}}; otherwise |this|.
-1. [=Safely set HTML=] given |target|, [=this=], |html|, and |options|.
+1. [=Set and filter HTML=] given |target|, [=this=], |html|, |options|, and `safe` set to `true`.
@@ -141,14 +141,18 @@ These methods are mirrored on the {{ShadowRoot}}:
-To
set and filter HTML, given an {{Element}} or {{DocumentFragment}} |target|, an {{Element}} |contextElement|, a [=string=] |html|, and a [=canonical=] |config|, run these steps:
-
+ |options|[`"sanitizer"`] and |safe|.
1. Let |newChildren| be the result of the HTML [=fragment parsing algorithm=]
given |contextElement|, |html|, and `true`.
1. Let |fragment| be a new {{DocumentFragment}} whose [=node document=] is |contextElement|'s [=node document=].
@@ -302,9 +256,9 @@ To
set and filter HTML, given an {{Element}} or {{DocumentFragment}}
For the main sanitize operation, using a {{ParentNode}} |node|, a
-[=canonical=] {{SanitizerConfig}} |config|, run these steps:
+[=SanitizerConfig/canonical=] {{SanitizerConfig}} |config|, run these steps:
-1. [=Assert=]: |config| is [=canonical=].
+1. [=Assert=]: |config| is [=SanitizerConfig/canonical=].
1. Initialize |current| with |node|.
1. [=list/iterate|For each=] |child| in |current|'s [=tree/children=]:
1. [=Assert=]: |child| [=implements=] {{Text}}, {{Comment}}, or {{Element}}.
@@ -315,195 +269,282 @@ For the main sanitize operation, using a {{ParentNode}} |node|, a
1. If |child| [=implements=] {{Text}}:
1. Do nothing.
1. else if |child| [=implements=] {{Comment}}:
- 1. If |config|'s {{CanonicalSanitizerConfig/comments}} is not `true`:
- 1. {{Node/removeChild()}} |child| from |current|.
+ 1. If |config|'s {{SanitizerConfig/comments}} is not `true`:
+ 1. [=/remove=] |child|.
1. else if |child| [=implements=] {{Element}}:
- 1. Let |element-name| be a {{CanonicalSanitizerName}} with |child|'s
+ 1. Let |elementName| be a {{SanitizerElementNamespace}} with |child|'s
[=Element/local name=] and [=Element/namespace=].
- 1. If |config|[{{CanonicalSanitizerConfig/elements}}] exists and
- |config|[{{CanonicalSanitizerConfig/elements}}] does not [=list/contain=]
- [|element-name|]:
- 1. Call {{Node/removeChild()}} on |child|.
- 1. else if |config|[{{CanonicalSanitizerConfig/removeElements}}] exists and
- |config|[{{CanonicalSanitizerConfig/removeElements}}] [=list/contains=]
- [|element-name|]:
- 1. Call {{Node/removeChild()}} on |child|.
- 1. If |config|[{{CanonicalSanitizerConfig/replaceWithChildrenElements}}] exists and |config|[{{CanonicalSanitizerConfig/replaceWithChildrenElements}}] [=list/contains=] |element-name|:
+ 1. If |config|["{{SanitizerConfig/elements}}"] exists and
+ |config|["{{SanitizerConfig/elements}}"] does not [=list/contain=]
+ [|elementName|]:
+ 1. [=/remove=] |child|.
+ 1. else if |config|["{{SanitizerConfig/removeElements}}"] exists and
+ |config|["{{SanitizerConfig/removeElements}}"] [=list/contains=]
+ [|elementName|]:
+ 1. [=/remove=] |child|.
+ 1. If |config|["{{SanitizerConfig/replaceWithChildrenElements}}"] exists and |config|["{{SanitizerConfig/replaceWithChildrenElements}}"] [=list/contains=] |elementName|:
1. Call [=sanitize=] on |child| with |config|.
- 1. Call {{ParentNode/replaceChildren()}} on |child| with |child|'s
- [=tree/children=] as arguments.
+ 1. Call [=replace all=] with |child|'s [=tree/children=] within |child|.
+ 1. If |elementName| [=equals=] «[ `"name"` → `"template"`,
+ `"namespace"` → [=HTML namespace=] ]»
+ 1. Then call [=sanitize=] on |child|'s [=template contents=] with |config|.
+ 1. If |child| is a [=shadow host=]:
+ 1. Then call [=sanitize=] on |child|'s [=Element/shadow root=] with |config|.
1. [=list/iterate|For each=] |attr| in |current|'s [=Element/attribute list=]:
- 1. Let |attr-name| be a {{CanonicalSanitizerName}} with |attr|'s
+ 1. Let |attrName| be a {{SanitizerAttributeNamespace}} with |attr|'s
[=Attr/local name=] and [=Attr/namespace=].
- 1. If |config|[{{CanonicalSanitizerConfig/attributes}}] exists and
- |config|[{{CanonicalSanitizerConfig/attributes}}] does not [=list/contain=]
- [attr-name|:
+ 1. If |config|["{{SanitizerConfig/attributes}}"] exists and
+ |config|["{{SanitizerConfig/attributes}}"] does not [=list/contain=]
+ |attrName|:
+ 1. If "data-" is a [=code unit prefix=] of [=Attr/local name=] and
+ if [=Attr/namespace=] is "" and
+ if |config|["{{SanitizerConfig/attributes}}"] exists and
+ if |config|["{{SanitizerConfig/dataAttributes}}"] exists and is `true`:
+ 1. Do nothing.
+ 1. Else:
+ 1. Remove |attr| from |child|.
+ 1. else if |config|["{{SanitizerConfig/removeAttributes}}"] exists and
+ |config|["{{SanitizerConfig/removeAttributes}}"] [=list/contains=]
+ |attrName|:
1. Remove |attr| from |child|.
- 1. else if |config|[{{CanonicalSanitizerConfig/removeAttributes}}] exists and
- |config|[{{CanonicalSanitizerConfig/removeAttributes}}] [=list/contains=]
- [attr-name|:
- 1. Remove |attr| from |child|.
- 1. If |config|[{{CanonicalSanitizerConfig/elements}}][|element-name|] exists,
+ 1. If |config|["{{SanitizerConfig/elements}}"][|elementName|] exists,
and if
- |config|[{{CanonicalSanitizerConfig/elements}}][|element-name|][{{CanonicalSanitizerNameWithAttributes/attributes}}]
+ |config|["{{SanitizerConfig/elements}}"][|elementName|]["{{SanitizerElementNamespaceWithAttributes/attributes}}"]
exists, and if
- |config|[{{CanonicalSanitizerConfig/elements}}][|element-name|][{{CanonicalSanitizerNameWithAttributes/attributes}}]
- does not [=list/contain=] |attr-name|:
+ |config|["{{SanitizerConfig/elements}}"][|elementName|]["{{SanitizerElementNamespaceWithAttributes/attributes}}"]
+ does not [=list/contain=] |attrName|:
1. Remove |attr| from |child|.
- 1. If |config|[{{CanonicalSanitizerConfig/elements}}][|element-name|] exists,
+ 1. If |config|["{{SanitizerConfig/elements}}"][|elementName|] exists,
and if
- |config|[{{CanonicalSanitizerConfig/elements}}][|element-name|][{{CanonicalSanitizerNameWithAttributes/removeAttributes}}]
+ |config|["{{SanitizerConfig/elements}}"][|elementName|]["{{SanitizerElementNamespaceWithAttributes/removeAttributes}}"]
exists, and if
- |config|[{{CanonicalSanitizerConfig/elements}}][|element-name|][{{CanonicalSanitizerNameWithAttributes/removeAttributes}}]
- [=list/contains=] |attr-name|:
- 1. If |child| is a [=Element/shadow host=]:
+ |config|["{{SanitizerConfig/elements}}"][|elementName|]["{{SanitizerElementNamespaceWithAttributes/removeAttributes}}"]
+ [=list/contains=] |attrName|:
+ 1. Remove |attr| from |child|.
+ 1. If «[|elementName|, |attrName|]» matches an entry in the
+ [=navigating URL attributes list=], and if |attr|'s [=protocol=] is
+ `"javascript:"`:
+ 1. Then remove |attr| from |child|.
1. Call [=sanitize=] on |child|'s [=Element/shadow root=] with |config|.
1. else:
- 1. Call {{Node/removeChild()}} on |child|.
+ 1. [=/remove=] |child|.
1. else:
1. [=Assert=]: We shouldn't reach this branch.
-TODO: Add "funky elements" / handling of `javascript:`-URLs back in.
-
## Configuration Processing ## {#configuration-processing}
-A |config| is valid if all these conditions are met:
-
-1. |config| [=conforms=] to {{SanitizerConfig}}.
-1. |config| [=map/keys=] contains either {{SanitizerConfig/elements}} or
- {{SanitizerConfig/removeElements}}, or neither of them, but not both.
-1. |config| [=map/keys=] contains either {{SanitizerConfig/removeAttributes}}
- or {{SanitizerConfig/attributes}}, or neither, but not both.
-1. If |config|[{{SanitizerConfig/elements}}] exists, then none of its members'
- [=map/keys=] contains both {{SanitizerElementNamespaceWithAttributes/attributes}}
- and {{SanitizerElementNamespaceWithAttributes/removeAttributes}}.
-1. TODO: check that name dictionaries must contain "name"
+A |config| is valid if all these conditions are met:
+
+1. |config| is a [=dictionary=]
+1. |config|'s [=map/keys|key set=] does not contain both
+ "{{SanitizerConfig/elements}}" and "{{SanitizerConfig/removeElements}}"
+1. |config|'s [=map/keys|key set=] does not contain both
+ "{{SanitizerConfig/removeAttributes}}" and "{{SanitizerConfig/attributes}}".
+1. [=list/iterate|For any=] |key| of «[
+ "{{SanitizerConfig/elements}}",
+ "{{SanitizerConfig/removeElements}}",
+ "{{SanitizerConfig/replaceWithChildrenElements}}",
+ "{{SanitizerConfig/attributes}}",
+ "{{SanitizerConfig/removeAttributes}}"
+ ]» where |config|[|key|] [=map/exists=]:
+ 1. |config|[|key|] is [=SanitizerNameList/valid=].
+1. If |config|["{{SanitizerConfig/elements}}"] exists, then
+ [=list/iterate|for any=] |element| in |config|[|key|] that is a [=dictionary=]:
+ 1. |element| does not contain both
+ "{{SanitizerElementNamespaceWithAttributes/attributes}}" and
+ "{{SanitizerElementNamespaceWithAttributes/removeAttributes}}".
+ 1. If either |element|["{{SanitizerElementNamespaceWithAttributes/attributes}}"]
+ or |element|["{{SanitizerElementNamespaceWithAttributes/removeAttributes}}"]
+ [=map/exists=], then it is [=SanitizerNameList/valid=].
-A |config| is canonical if all these conditions are met:
-
-1. |config| is [=valid=].
-1. |config| [=strictly conforms=] to {{CanonicalSanitizerConfig}}.
-1. |config|'s [=map/keys|key set=] [=set/equals=] any of:
- 1. «
- {{SanitizerConfig/elements}},
- {{SanitizerConfig/attributes}},
- {{SanitizerConfig/comments}}
- »
- 1. «
- {{SanitizerConfig/elements}},
- {{SanitizerConfig/replaceWithChildrenElements}},
- {{SanitizerConfig/attributes}},
- {{SanitizerConfig/comments}}
- »
- 1. «
- {{SanitizerConfig/removeElements}},
- {{SanitizerConfig/removeAttributes}},
- {{SanitizerConfig/comments}}
- »
- 1. «
- {{SanitizerConfig/removeElements}},
- {{SanitizerConfig/removeAttributes}},
- {{SanitizerConfig/replaceWithChildrenElements}},
- {{SanitizerConfig/comments}}
- »
-1. TODO: Elements with attributes
+A |list| of names is valid if all these
+conditions are met:
+
+1. |list| is a [=/list=].
+1. [=list/iterate|For all=] of its members |name|:
+ 1. |name| is a {{string}} or a [=dictionary=].
+ 1. If |name| is a [=dictionary=]:
+ 1. |name|["{{SanitizerElementNamespace/name}}"] [=map/exists=] and is a {{string}}.
+
+A |config| is canonical if all these conditions are met:
+
+1. |config| is [=SanitizerConfig/valid=].
+1. |config|'s [=map/keys|key set=] is a [=set/subset=] of
+ «[
+ "{{SanitizerConfig/elements}}",
+ "{{SanitizerConfig/removeElements}}",
+ "{{SanitizerConfig/replaceWithChildrenElements}}",
+ "{{SanitizerConfig/attributes}}",
+ "{{SanitizerConfig/removeAttributes}}",
+ "{{SanitizerConfig/comments}}",
+ "{{SanitizerConfig/dataAttributes}}",
+ "safe"
+ ]»
+1. |config|'s [=map/keys|key set=] contains either:
+ 1. both "{{SanitizerConfig/elements}}" and "{{SanitizerConfig/attributes}}",
+ but neither of
+ "{{SanitizerConfig/removeElements}}" or "{{SanitizerConfig/removeAttributes}}".
+ 1. or both
+ "{{SanitizerConfig/removeElements}}" and "{{SanitizerConfig/removeAttributes}}",
+ but neither of
+ "{{SanitizerConfig/elements}}" or "{{SanitizerConfig/attributes}}".
+1. For any |key| of «[
+ "{{SanitizerConfig/replaceWithChildrenElements}}",
+ "{{SanitizerConfig/removeElements}}",
+ "{{SanitizerConfig/attributes}}",
+ "{{SanitizerConfig/removeAttributes}}"
+ ]» where |config|[|key|] [=map/exists=]:
+ 1. |config|[|key|] is [=SanitizerNameList/canonical=].
+1. If |config|["{{SanitizerConfig/elements}}"] [=map/exists=]:
+ 1. |config|["{{SanitizerConfig/elements}}"] is [=SanitizerNameWithAttributesList/canonical=].
+1. For any |key| of «[
+ "{{SanitizerConfig/comments}}",
+ "{{SanitizerConfig/dataAttributes}}",
+ "safe"
+ ]»:
+ 1. if |config|[|key|] [=map/exists=], |config|[|key|] is a {{boolean}}.
+
+
+
+
+A |list| of names is canonical if all these
+conditions are met:
+
+1. |list|[|key|] is a [=/list=].
+1. [=list/iterate|For all=] of its |list|[|key|]'s members |name|:
+ 1. |name| is a [=dictionary=].
+ 1. |name|'s [=map/keys|key set=] [=set/equals=] «[
+ "{{SanitizerElementNamespace/name}}", "{{SanitizerElementNamespace/namespace}}"
+ ]»
+ 1. |name|'s [=map/values=] are [=string=]s.
+
+
+
+
+A |list| of names is canonical
+if all these conditions are met:
+
+1. |list|[|key|] is a [=/list=].
+1. [=list/iterate|For all=] of its |list|[|key|]'s members |name|:
+ 1. |name| is a [=dictionary=].
+ 1. |name|'s [=map/keys|key set=] [=set/equals=] one of:
+ 1. «[
+ "{{SanitizerElementNamespace/name}}",
+ "{{SanitizerElementNamespace/namespace}}"
+ ]»
+ 1. «[
+ "{{SanitizerElementNamespace/name}}",
+ "{{SanitizerElementNamespace/namespace}}",
+ "{{SanitizerElementNamespaceWithAttributes/attributes}}"
+ ]»
+ 1. «[
+ "{{SanitizerElementNamespace/name}}",
+ "{{SanitizerElementNamespace/namespace}}",
+ "{{SanitizerElementNamespaceWithAttributes/removeAttributes}}"
+ ]»
+ 1. |name|["{{SanitizerElementNamespace/name}}"] and
+ |name|["{{SanitizerElementNamespace/namespace}}"] are [=string=]s.
+ 1. |name|["{{SanitizerElementNamespaceWithAttributes/attributes}}"] and
+ |name|["{{SanitizerElementNamespaceWithAttributes/removeAttributes}}"]
+ are [=SanitizerNameList/canonical=] if they [=map/exist=].
+
+
+
+
In order to canonicalize a configuration |config| with a boolean
parameter |safe|, run the following steps:
TODO: Handle empty |config|.
-1. If |config| is not [=valid=], then [=throw=] a {{TypeError}}.
+1. If |config| is not [=SanitizerConfig/valid=], then [=throw=] a {{TypeError}}.
1. Let |result| be a new [=dictionary=].
-1. For each |key| of
- {{SanitizerConfig/elements}},
- {{SanitizerConfig/removeElements}},
- {{SanitizerConfig/replaceWithChildrenElements}}:
+1. For each |key| of «[
+ "{{SanitizerConfig/elements}}",
+ "{{SanitizerConfig/removeElements}}",
+ "{{SanitizerConfig/replaceWithChildrenElements}}" ]»:
1. If |config|[|key|] exists, set |result|[|key|] to the result of running
[=canonicalize a sanitizer element list=] on |config|[|key|] with
[=HTML namespace=] as the default namespace.
-1. For each |key| of
- {{SanitizerConfig/attributes}},
- {{SanitizerConfig/removeAttributes}}:
+1. For each |key| of «[
+ "{{SanitizerConfig/attributes}}",
+ "{{SanitizerConfig/removeAttributes}}" ]»:
1. If |config|[|key|] exists, set |result|[|key|] to the result of running
[=canonicalize a sanitizer element list=] on |config|[|key|] with `""` as
the default namespace.
-1. Set |result|[{{SanitizerConfig/comments}}] to
- |config|[{{SanitizerConfig/comments}}].
+1. Set |result|["{{SanitizerConfig/comments}}"] to
+ |config|["{{SanitizerConfig/comments}}"].
1. Let |default| be the result of [=canonicalizing a configuration=] for the
[=built-in default config=].
1. If |safe|:
- 1. Let |known elements| be an [=ordered set=] of all elements known to the
- [[HTML]] specification, where the set members [=strictly conform=] to
- {{CanonicalSanitizerName}}.
- 1. Let |known attributes| be an [=ordered set=] of all attributes known to the
- [[HTML]] specification, where the set members [=strictly conform=] to
- {{CanonicalSanitizerName}}.
- 1. If |config|[{{SanitizerConfig/elements}}] [=map/exists=]:
- 1. Set |result|[{{SanitizerConfig/elements}}] to the
- [=intersection complement=] of |result|[{{SanitizerConfig/elements}}] and
- the [=intersection complement=] of |known elements| and
- |default|[{{SanitizerConfig/elements}}].
-
- Note: This sounds more complicated than it is. This the same as the
- [=set/intersection=] of |result|[{{SanitizerConfig/elements}}] and
- |default|[{{SanitizerConfig/elements}}], except that it also
- preserves unknown HTML elements, which a plain [=set/intersection=]
- would remove.
- 1. If |config|[{{SanitizerConfig/removeElements}}] [=map/exists=]:
- 1. Set |result|[{{SanitizerConfig/elements}}] to the
- [=intersection complement=] of |default|[{{SanitizerConfig/elements}}]
- and |result|[{{SanitizerConfig/removeElements}}].
- 1. [=set/Remove=] {{SanitizerConfig/removeElements}} from |result|.
- 1. If neither |config|[{{SanitizerConfig/elements}}] nor
- |config|[{{SanitizerConfig/removeElements}}] [=map/exist=]:
- 1. Set |result|[{{SanitizerConfig/elements}}] to
- |default|[{{SanitizerConfig/elements}}].
- 1. If |config|[{{SanitizerConfig/attributes}}] [=map/exists=]:
- 1. Set |result|[{{SanitizerConfig/attributes}}] to the
- [=intersection complement=] of |result|[{{SanitizerConfig/attributes}}] and
- the [=intersection complement=] attributes |known attributes| and
- |default|[{{SanitizerConfig/attributes}}].
- 1. If |config|[{{SanitizerConfig/removeAttributes}}] [=map/exists=]:
- 1. Set |result|[{{SanitizerConfig/attributes}}] to the
- [=intersection complement=] of |default|[{{SanitizerConfig/attributes}}]
- and |result|[{{SanitizerConfig/removeAttributes}}].
- 1. [=set/Remove=] {{SanitizerConfig/removeAttributes}} from |result|.
- 1. If neither |config|[{{SanitizerConfig/attributes}}] nor
- |config|[{{SanitizerConfig/removeAttributes}}] [=map/exist=]:
- 1. Set |result|[{{SanitizerConfig/attributes}}] to
- |default|[{{SanitizerConfig/attributes}}].
+ 1. If |config|["{{SanitizerConfig/elements}}"] [=map/exists=]:
+ 1. Let |elementBlockList| be the [=set/difference=] between
+ [=known elements=] |default|["{{SanitizerConfig/elements}}"].
+
+ Note: The "natural" way to enforce the default element list would be
+ to intersect with it. But that would also eliminate any unknown
+ (i.e., non-HTML supplied element, like <foo>). So we
+ construct this helper to be able to use it to subtract any "unsafe"
+ elements.
+ 1. Set |result|["{{SanitizerConfig/elements}}"] to the
+ [=set/difference=] of |result|["{{SanitizerConfig/elements}}"] and
+ |elementBlockList|.
+ 1. If |config|["{{SanitizerConfig/removeElements}}"] [=map/exists=]:
+ 1. Set |result|["{{SanitizerConfig/elements}}"] to the
+ [=set/difference=] of |default|["{{SanitizerConfig/elements}}"]
+ and |result|["{{SanitizerConfig/removeElements}}"].
+ 1. [=set/Remove=] "{{SanitizerConfig/removeElements}}" from |result|.
+ 1. If neither |config|["{{SanitizerConfig/elements}}"] nor
+ |config|["{{SanitizerConfig/removeElements}}"] [=map/exist=]:
+ 1. Set |result|["{{SanitizerConfig/elements}}"] to
+ |default|["{{SanitizerConfig/elements}}"].
+ 1. If |config|["{{SanitizerConfig/attributes}}"] [=map/exists=]:
+ 1. Let |attributeBlockList| be the [=set/difference=] between
+ [=known attributes=] and |default|["{{SanitizerConfig/attributes}}"];
+ 1. Set |result|["{{SanitizerConfig/attributes}}"] to the
+ [=set/difference=] of |result|["{{SanitizerConfig/attributes}}"] and
+ |attributeBlockList|.
+ 1. If |config|["{{SanitizerConfig/removeAttributes}}"] [=map/exists=]:
+ 1. Set |result|["{{SanitizerConfig/attributes}}"] to the
+ [=set/difference=] of |default|["{{SanitizerConfig/attributes}}"]
+ and |result|["{{SanitizerConfig/removeAttributes}}"].
+ 1. [=set/Remove=] "{{SanitizerConfig/removeAttributes}}" from |result|.
+ 1. If neither |config|["{{SanitizerConfig/attributes}}"] nor
+ |config|["{{SanitizerConfig/removeAttributes}}"] [=map/exist=]:
+ 1. Set |result|["{{SanitizerConfig/attributes}}"] to
+ |default|["{{SanitizerConfig/attributes}}"].
1. Else (if not |safe|):
- 1. If neither |config|[{{SanitizerConfig/elements}}] nor
- |config|[{{SanitizerConfig/removeElements}} [=map/exist=]:
- 1. Set |result|[{{SanitizerConfig/elements}}] to
- |default|[{{SanitizerConfig/elements}}].
- 1. If neither |config|[{{SanitizerConfig/attributes}}] nor
- |config|[{{SanitizerConfig/removeAttributes}} [=map/exist=]:
- 1. Set |result|[{{SanitizerConfig/attributes}}] to
- |default|[{{SanitizerConfig/attributes}}].
-1. [=Assert=]: |result| is [=valid=].
-1. [=Assert=]: |result| is [=canonical=].
+ 1. If neither |config|["{{SanitizerConfig/elements}}"] nor
+ |config|["{{SanitizerConfig/removeElements}}"] [=map/exist=]:
+ 1. Set |result|["{{SanitizerConfig/elements}}"] to
+ |default|["{{SanitizerConfig/elements}}"].
+ 1. If neither |config|["{{SanitizerConfig/attributes}}"] nor
+ |config|["{{SanitizerConfig/removeAttributes}}"] [=map/exist=]:
+ 1. Set |result|["{{SanitizerConfig/attributes}}"] to
+ |default|["{{SanitizerConfig/attributes}}"].
+1. Set |result|["safe"] to |safe|.
+1. [=Assert=]: |result| is [=SanitizerConfig/valid=].
+1. [=Assert=]: |result| is [=SanitizerConfig/canonical=].
1. Return |result|.
In order to
canonicalize a sanitizer element list |list|, with a
-default namespace |default namespace|, run the following steps:
+default namespace |defaultNamespace|, run the following steps:
1. Let |result| be a new [=ordered set=].
2. [=list/iterate|For each=] |name| in |list|, call
- [=canonicalize a sanitizer name=] on |name| with |default namespace| and
+ [=canonicalize a sanitizer name=] on |name| with |defaultNamespace| and
[=set/append=] to |result|.
3. Return |result|.
@@ -511,63 +552,43 @@ default namespace |default namespace|, run the following steps:
In order to canonicalize a sanitizer name |name|, with a default
-namespace |default namespace|, run the following steps:
+namespace |defaultNamespace|, run the following steps:
1. [=Assert=]: |name| is either a {{DOMString}} or a [=dictionary=].
1. If |name| is a {{DOMString}}:
- 1. Return «[ `"name"` → |name|, `"namespace"` → |default namespace|]».
+ 1. Return «[ `"name"` → |name|, `"namespace"` → |defaultNamespace|]».
1. [=Assert=]: |name| is a [=dictionary=] and |name|["name"] [=map/exists=].
1. Return «[
`"name"` → |name|["name"],
- `"namespace"` → |name|["namespace"] if it [=map/exists=], otherwise |default namespace|
+ `"namespace"` → |name|["namespace"] if it [=map/exists=], otherwise |defaultNamespace|
]».
## Supporting Algorithms ## {#alg-support}
-
-The intersection complement of two [=ordered sets=] |A| and |B|, is
-the result of creating a new [=ordered set=] |set| and, [=list/iterate|for each=]
-|item| of |A|, if |B| does not [=set/contain=] item, [=set/appending=] |item| to
-|set|.
-
-Note: [=intersection complement=] is the same as [=set/intersection=], but with the
- complement of parameter |B|.
-
+Set difference (or set subtraction) is a clone of a set A, but with all members
+removed that occur in a set B.
-[=Ordered sets=] |A| and |B| are equal if both |A| is a [=superset=] of
-|B| and |B| is a [=superset=] of |A|.
+To compute the difference of two [=ordered sets=] |A| and |B|:
-Note: Equality for [=ordered sets=] is equality of its members, but without
-regard to order.
-
+1. Let |set| be a new [=ordered set=].
+1. [=list/iterate|For each=] |item| of |A|:
+ 1. If |B| does not [=set/contain=] |item|, then [=set/append=] |item|
+ to |set|.
+1. Return |set|.
-
-A value |D| conforms to a
-[=dictionary|dictionary definition=] if |D| is a [=map=] and all of |D|'s [=map/entries=]
-corrspond to [=dictionary members=], as long as those entries have the correct
-types, and there are [=map/entries=] present for any [=dictionary member/required=] or
-[=dictionary member/default value|defaulted=] dictionary members, and any [=dictionary=]-typed values [=conform=] to their [=dictionary member=]'s type.
-
-Note: This largely corresponds to language in [=dictionary=], but re-words this
-as a predicate.
-
-A value |D|
strictly conforms to a
-[=dictionary|dictionary definition=] if
-
-1. |D| [=conforms=] to the definition,
-1. there are no [=map/entries=] present that do not have a corresponding
- [=dictionary member=], and
-1. [=dictionary=]-valued members [=strictly conform=] to their
- [=dictionary member=]'s type.
+Equality for [=ordered sets=] is equality of its members, but without
+regard to order.
+
+[=Ordered sets=] |A| and |B| are equal if both |A| is a
+[=superset=] of |B| and |B| is a [=superset=] of |A|.
-
## Defaults ## {#sanitization-defaults}
The
built-in default config is as follows:
@@ -576,9 +597,73 @@ The
built-in default config is as follows:
elements: [....],
attributes: [....],
comments: true,
+ safe: true,
}
```
+The
known elements are as follows:
+```
+[
+ { name: "div", namespace: "http://www.w3.org/1999/xhtml"" },
+ ...
+]
+```
+
+The
known attributes are as follows:
+```
+[
+ { name: "class", namespace: "" },
+ ...
+]
+```
+
+1. [=Assert=]: [=built-in default config=] is [=SanitizerConfig/canonical=]
+1. [=Assert=]: [=built-in default config=]["elements"] is a [=subset=] of [=known elements=].
+1. [=Assert=]: [=built-in default config=]["attributes"] is a [=subset=] of [=known attributes=].
+1. [=Assert=]: «[
+ "elements" → [=known elements=],
+ "attributes" → [=known attributes=],
+ "safe" → `false`,
+ ]» is [=SanitizerConfig/canonical=].
+
+Note: The [=known elements=] and [=known attributes=] should be derived from the
+ HTML5 specification, rather than being explicitly listed here. Currently,
+ there are no mechanics to do so.
+
+
+The navigating URL attributes list, for which "`javascript:`"
+navigations are unsafe, are as follows:
+
+«[
+
+ [
+ { `"name"` → `"a"`, `"namespace"` → "[=HTML namespace=]" },
+ { `"name"` → `"href"`, `"namespace"` → "" }
+ ],
+
+ [
+ { `"name"` → `"area"`, `"namespace"` → "[=HTML namespace=]" },
+ { `"name"` → `"href"`, `"namespace"` → "" }
+ ],
+
+ [
+ { `"name"` → `"form"`, `"namespace"` → "[=HTML namespace=]" },
+ { `"name"` → `"action"`, `"namespace"` → "" }
+ ],
+
+ [
+ { `"name"` → `"input"`, `"namespace"` → "[=HTML namespace=]" },
+ { `"name"` → `"formaction"`, `"namespace"` → "" }
+ ],
+
+ [
+ { `"name"` → `"button"`, `"namespace"` → "[=HTML namespace=]" },
+ { `"name"` → `"formaction"`, `"namespace"` → "" }
+ ],
+
+]»
+
+
# Security Considerations # {#security-considerations}