diff --git a/index.bs b/index.bs index 08e53ca..b31739f 100644 --- a/index.bs +++ b/index.bs @@ -195,7 +195,7 @@ The parseHTMLUnsafe(|html|, |options|) method s 1. [=Parse HTML from a string=] given |document| and |compliantHTML|. 1. Let |sanitizer| be the result of calling [=get a sanitizer instance from options=] with |options|. -1. Call [=sanitize=] on |document|'s [=tree/root|root node=] with |sanitizer|. +1. Call [=sanitize=] on |document|'s [=tree/root|root node=] with |sanitizer| and false. 1. Return |document|. @@ -211,7 +211,7 @@ The parseHTML(|html|, |options|) method steps a 1. [=Parse HTML from a string=] given |document| and |html|. 1. Let |sanitizer| be the result of calling [=get a sanitizer instance from options=] with |options|. -1. Call [=sanitize=] on |document|'s [=tree/root|root node=] with |sanitizer|. +1. Call [=sanitize=] on |document|'s [=tree/root|root node=] with |sanitizer| and true. 1. Return |document|. @@ -228,38 +228,45 @@ dictionary SetHTMLOptions { The {{Sanitizer}} configuration object encapsulates a filter configuration. -The same config can be used with both safe or unsafe methods. The intent is +The same config can be used with both safe or unsafe methods, where the safe +methods perform an implicit {{removeUnsafe}} operation. The intent is that one (or a few) configurations will be built-up early on in a page's lifetime, and can then be used whenever needed. This allows implementations to pre-process configurations. -The configuration object is also query-able and can return -configuration dictionaries, -in both safe and unsafe variants. This allows a -page to query and predict what effect a given configuration will have, or -to build a new configuration based on an existing one. +The configuration object can be queried to return a configuration dictionary. +It can also be modified directly.
[Exposed=(Window,Worker)] interface Sanitizer { constructor(optional SanitizerConfig config = {}); - // Query configurations: + // Query configuration: SanitizerConfig get(); - SanitizerConfig getUnsafe(); - // Modifying a Sanitizer: - undefined element(SanitizerElementNamespaceWithAttributes element); + // Modify a Sanitizer's lists and fields: + undefined allowElement(SanitizerElementNamespaceWithAttributes element); undefined removeElement(SanitizerElement element); - undefined replaceWithChildren(SanitizerElement element); + undefined replaceWithChildrenElement(SanitizerElement element); undefined allowAttribute(SanitizerAttribute attribute); undefined removeAttribute(SanitizerAttribute attribute); undefined setComment(boolean allow); undefined setDataAttributes(boolean allow); undefined setOtherMarkup(boolean allow); + + // Remove markup that executes script. May modify multiple lists: + undefined removeUnsafe(); };+ISSUE(238): Final naming TBD. + +ISSUE(240): "other markup" TBD. + +ISSUE: Should these be setter methods -- particularly the setXXX(boolean) -- + or setters or properties or somesuch? +
@@ -426,14 +432,14 @@ To set and filter HTML, given an {{Element}} or {{DocumentFragment}} To get a sanitizer instance from options for an options dictionary |options|, do: -1. Assert: |options| is a [=dictionary=]. +1. [=Assert=]: |options| is a [=dictionary=]. 1. If |options|["`sanitizer`"] doesn't [=map/exist=], then return new {{Sanitizer}}(). -1. Assert: |options|["`sanitizer`"] is either a {{Sanitizer}} instance +1. [=Assert=]: |options|["`sanitizer`"] is either a {{Sanitizer}} instance or a [=dictionary=]. 1. If |options|["`sanitizer`"] is a {{Sanitizer}} instance: Then return |options|["`sanitizer`"]. -1. Assert: |options|["`sanitizer`"] is a [=dictionary=]. +1. [=Assert=]: |options|["`sanitizer`"] is a [=dictionary=]. 1. Return new {{Sanitizer}}(|options|["`sanitizer`"]). @@ -445,7 +451,7 @@ For the main sanitize operation, using a {{ParentNode}} |node|, a {{Sanitizer}} |sanitizer| and a [=boolean=] |safe|, run these steps: 1. Let |config| be the value of |sanitizer|'s [=internal slot=]. -1. If |safe|, let |config| be the result of calling [=safeify=] on |config|. +1. If |safe|, let |config| be the result of calling [=remove unsafe=] on |config|. 1. Call [=sanitize core=] on |node|, |config|, and |safe| (as value for handling javascript navigation urls). @@ -455,7 +461,7 @@ For the main sanitize operation, using a {{ParentNode}} |node|, a The sanitize core operation, using a {{ParentNode}} |node|, a {{SanitizerConfig}} |config|, and a [=boolean=] |handle javascript navigation urls|, iterates over the DOM tree -beginning with |node|, and may recurse to handle some special cases (e.g. +beginning with |node|, and may recurse to handle some special cases (e.g. template contents). It consistes of these steps: 1. Let |current| be |node|. @@ -506,7 +512,7 @@ template contents). It consistes of these steps: [=Attr/namespace=] is `null` and |config|["{{SanitizerConfig/dataAttributes}}"] is true - |config|["{{SanitizerConfig/otherMarkup}}"] - 1. If |handle javascript navigation urls|and «[|elementName|, |attrName|]» matches an entry in the + 1. If |handle javascript navigation urls| and «[|elementName|, |attrName|]» matches an entry in the [=navigating URL attributes list=], and if |attr|'s [=protocol=] is "`javascript:`": 1. Then remove |attr| from |child|. @@ -516,7 +522,14 @@ template contents). It consistes of these steps: ## Configuration Processing ## {#configuration-processing}-To safeify a |config|, do this: + +Note: While this algorithm is called [=remove unsafe=], we use + the term "unsafe" strictly in the sense + of this spec, to denote content that will + execute JavaScript when inserted into the document. In other words, this + method will remove oportunities for XSS. + +To remove unsafe from a |config|, do this: 1. [=Assert=]: The [=built-in safe baseline config=] has {{SanitizerConfig/removeElements}} and {{SanitizerConfig/removeAttributes}} @@ -526,10 +539,10 @@ To safeify a |config|, do this: 1. Let |result| be a copy of |config|. 1. [=list/For each=] |elem| in [=built-in safe baseline config=][{{SanitizerConfig/removeElements}}]: - 1. Call |result|.removeElement(|elem|) + 1. Call |result|.{{Sanitizer/removeElement()|removeElement}}(|elem|) 1. [=list/For each=] |attr| in [=built-in safe baseline config=][{{SanitizerConfig/removeAttributes}}]: - 1. Call |result|.removeAttributes(|attr|) + 1. Call |result|.{{Sanitizer/removeAttribute()|removeAttribute}}(|attr|) 1. Return |result|.@@ -539,18 +552,18 @@ To set a config |config| on a {{Sanitizer}} |sanitize 1. [=Assert=]: |config| is a [=dictionary=]. 1. [=list/iterate|For each=] |item| of |config|[{{SanitizerConfig/elements}}] do: - 1. Call |sanitizer|.element(|item|). + 1. Call |sanitizer|.{{Sanitizer/allowElement()|allowElement}}(|item|). 1. [=list/iterate|For each=] |item| of |config|[{{SanitizerConfig/removeElements}}] do: - 1. Call |sanitizer|.removeElement(|item|). + 1. Call |sanitizer|.{{Sanitizer/removeElement()|removeElement}}(|item|). 1. [=list/iterate|For each=] |item| of |config|[{{SanitizerConfig/replaceWithChildrenElements}}] do: - 1. Call |sanitizer|.replaceWithChildren(|item|). + 1. Call |sanitizer|.{{Sanitizer/replaceWithChildrenElement()|replaceWithChildrenElement}}(|item|). 1. [=list/iterate|For each=] |item| of |config|[{{SanitizerConfig/attributes}}] do: - 1. Call |sanitizer|.attribute(|item|). + 1. Call |sanitizer|.{{Sanitizer/allowAttribute()|allowAttribute}}(|item|). 1. [=list/iterate|For each=] |item| of |config|[{{SanitizerConfig/removeAttributes}}] do: - 1. Call |sanitizer|.removeAttributes(|item|). -1. Call |sanitizer|.comments(|config|[{{SanitizerConfig/comments}}]). -1. Call |sanitizer|.dataAttributes(|config|[{{SanitizerConfig/dataAttributes}}]). -1. Call |sanitizer|.otherMarkup(|config|[{{SanitizerConfig/otherMarkup}}]). + 1. Call |sanitizer|.{{Sanitizer/removeAttribute()|removeAttribute}}(|item|). +1. Call |sanitizer|.{{Sanitizer/setComment()|setComment}}(|config|[{{SanitizerConfig/comments}}]). +1. Call |sanitizer|.{{Sanitizer/setDataAttributes()|setDataAttributes}}(|config|[{{SanitizerConfig/dataAttributes}}]). +1. Call |sanitizer|.{{Sanitizer/setOtherMarkup()|setOtherMarkup}}(|config|[{{SanitizerConfig/otherMarkup}}]). Note: Previous versions of this spec had elaborate definitions of how to canonicalize a config. This has now effectively been moved into the method @@ -572,13 +585,40 @@ namespace |defaultNamespace|, run the following steps: -## Supporting Algorithms ## {#alg-support} ++To add a |name| to a |list|, where |name| is +[=canonicalize a sanitizer name|canonicalized=] and |list| is an [=ordered map=]: + +1. If |list| [=SanitizerConfig/contains=] |name|, then return. +1. [=list/Append=] |name| to |list|. + ++To merge attribute lists of an |element| to a +|list|, run these steps: + +1. [=Assert=]: |element| is an {{SanitizerElementNamespaceWithAttributes}}. +1. [=Assert=]: |list| [=SanitizerConfig/contains=] |element|. +1. [=list/iterate|For each=] |attr| in + |element|[{{SanitizerElementNamespaceWithAttributes/attributes}}], + [=SanitizerConfig/add=] |attr| to + |list|[|element|][{{SanitizerElementNamespaceWithAttributes/attributes}}]. +1. [=list/iterate|For each=] |attr| in + |element|[{{SanitizerElementNamespaceWithAttributes/removeAttributes}}], + [=SanitizerConfig/add=] |attr| to + |list|[|element|][{{SanitizerElementNamespaceWithAttributes/removeAttributes}}]. + ++ +## Supporting Algorithms ## {#alg-support} + For the [=canonicalize a sanitizer name|canonicalized=] {{SanitizerElementNamespace|element}} and {{SanitizerAttributeNamespace|attribute name}} lists used in this spec, list membership is based on matching both "`name`" and "`namespace`" entries: + +A Sanitizer name |list| contains an |item| if there exists an |entry| of |list| that is an [=ordered map=], and where |item|["name"] [=equals=] |entry|["name"] and @@ -586,19 +626,6 @@ if there exists an |entry| of |list| that is an [=ordered map=], and where--Set difference (or set subtraction) is a clone of a set A, but with all members -removed that occur in a set B: -To compute the difference of two [=ordered sets=] |A| and |B|: - -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|. - --Equality for [=ordered sets=] is equality of its members, but without regard to order: