1. 序論
◎非規範的~web~appは、 ~client側で,~HTMLを成す文字列で作業する必要があることが多い — たぶん[ ~client側における~template化による解決策 ]や[ 利用者が生成した内容の具現化 ], 等々を成す一部として。 それを安全な仕方で行うのは困難である — [ 文字列を~~連結して, `Element$I の `innerHTML$mE の中へ詰め込む ]ような素朴な~approachは、 いくつかの期待されない仕方で~JSを実行させ得るので, ~riskをはらんでいる。 ◎ Web applications often need to work with strings of HTML on the client side, perhaps as part of a client-side templating solution, perhaps as part of rendering user generated content, etc. 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 JavaScript execution in a number of unexpected ways.
`DOMPURIFY$r の様な~libraryは、 文字列を挿入する前に,[ それを注意深く構文解析して~DOMを構築してから、 許容-~listを通して,その~memberたちを~filterして無毒化する ]ことにより,この問題を管理しようと試みる。 これは、 脆い~approachであることが立証された — ~webに公開された【~libraryの】構文解析~APIは、 文字列を “本物の” ~DOM内に~HTMLとして実際に具現化するとき,常に[ 適理な仕方で,~browserの挙動に対応付ける ]とは限らないので。 さらには、 ~libraryが[ 時間~越しに変化していく~browserの挙動 ]の~~上層にあることを保つ必要もある — それまで安全だったものは、 ~platform~levelの新たな特能に基づいて時限爆弾に転化し得るので。 ◎ 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.
~browserは、 ~codeをいつ実行しようとするかについて,よく知る立場にある。 利用元~空間の~libraryは,次により改善でき、 この文書は,まさにそれを目指す~APIを要旨する ⇒ 任意な文字列から安全な方式で~HTMLを具現化するにあたって,次を可能にする ⇒ それを行う方法を~browserに教えること、 および[ ~browserによる自前の[ 構文解析器の実装 ]が変化するに伴い[ 保守される/更新される ]見込みがずっと高い仕方で,それを行うこと ◎ The browser has a fairly good idea of when it is going to execute code. We can improve upon the 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. This document outlines an API which aims to do just that.
1.1. 目標
- 次により,~DOMに基づく~XSS攻撃の~riskを軽減する ⇒ ~HTMLを取扱うための[ 利用元により制御される仕組み ]を開発者に供して、 注入の際に直な~script実行を防止する ◎ Mitigate the risk of DOM-based cross-site scripting attacks by providing developers with mechanisms for handling user-controlled HTML which prevent direct script execution upon injection.
- ~HTML出力を現在の~UAの中で安全に利用できるようにする — ~UAの[ ~HTMLに対する現在の理解 ]を織り込む下で。 ◎ Make HTML output safe for use within the current user agent, taking into account its current understanding of HTML.
- 対象になる[ 要素/属性 ]たちが成す既定の集合を上書きすることを,開発者に許容する。 ある種の[ 要素/属性 ]をそこに追加することは、 `~script~gadget攻撃@https://github.com/google/security-research-pocs/tree/master/script-gadgets$を防止し得る。 ◎ Allow developers to override the default set of elements and attributes. Adding certain elements and attributes can prevent script gadget attacks.
1.2. ~APIの要約
`無毒化器~API^i( `Sanitizer API^en )は、[ ~HTMLを包含している文字列を~DOM~treeへ構文解析して, 結果の~treeを利用者が給した環境設定に則って~filterする ]ための機能性を提供する。 ~APIは、 次に挙げる 2 × 2 種の味付けを伴う~methodとして供される: ◎ The Sanitizer API offers 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 by two flavours:
- 安全か否か: “安全な” ~methodは、 ~scriptを実行する~markupを生成しないことになる。 すなわち、 それらは,~XSSから安全になるはずである。 “安全でない” ~methodは、 何であれ,想定されるものを[ 構文解析する, ~filterする ]ことになる。 ◎ Safe and unsafe: The "safe" methods will not generate any markup that executes script. That is, they should be safe from XSS. The "unsafe" methods will parse and filter whatever they’re supposed to.
- 文脈: ~methodは、[ `Element$I, `ShadowRoot$I ]上に定義され, これらの `Node$I の子~群を置換することになる — それは、 `innerHTML$mE に~~概ね相似的である。 `Document$I 上にも静的な~methodがあり、 文書~全体に対し構文解析する — それは、 `DOMParser$I の `parseFromString()$m に~~概ね相似的である。 ◎ 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 are largely analogous to DOMParser.parseFromString().
2. ~framework
2.1. 無毒化器~API
`Element$I ~interfaceは、 2 つの~method — `setHTML()$mE, `setHTMLUnsafe()$mE — を定義する。 これらは、 どちらも[ ~HTML~markupを伴う`文字列$, 省略可能な環境設定 ]をとる。 ◎ The Element interface defines two methods, setHTML() and setHTMLUnsafe(). Both of these take a DOMString with HTML markup, and an optional configuration.
partial interface `Element$I { [`CEReactions$] `undefined$ `setHTMLUnsafe$mE((`TrustedHTML$ or `DOMString$) %html, optional `SetHTMLOptions$I %options = {}); [`CEReactions$] `undefined$ `setHTML$mE(`DOMString$ %html, optional `SetHTMLOptions$I %options = {}); };
`Element$I の `setHTMLUnsafe(html, options)@mE ~method手続きは: ◎ Element's setHTMLUnsafe(html, options) method steps are:
- %準拠~HTML ~LET `信用-済みな型に準拠な文字列を取得する$( ↓ ) ⇒# `TrustedHTML$I, コレに`関連な大域~obj$, %html, `Element setHTMLUnsafe^l, `script^l ◎ 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".
- %~target ~LET コレ ◎ ↓
- ~IF[ コレは `HTMLTemplateElement$I 要素である ] ⇒ %~target ~SET コレの`~template内容$ ◎ Let target be this's template contents if this is a template element; otherwise this.
- `~HTMLを設定して~filterする$( ↓ ) ⇒# %~target, コレ, %準拠~HTML*, %options, ~F ◎ Set and filter HTML given target, this, compliantHTML, options, and false.
`Element$I の `setHTML(html, options)@mE ~method手続きは: ◎ Element's setHTML(html, options) method steps are:
- %~target ~LET コレ ◎ ↓
- ~IF[ コレは `HTMLTemplateElement$I 要素である ] ⇒ %~target ~SET コレの`~template内容$ ◎ Let target be this's template contents if this is a template; otherwise this.
- `~HTMLを設定して~filterする$( ↓ ) ⇒# %~target, コレ, %html, %options, ~T ◎ Set and filter HTML given target, this, html, options, and true.
partial interface `ShadowRoot$I { [`CEReactions$] `undefined$ `setHTMLUnsafe$m((`TrustedHTML$ or `DOMString$) %html, optional `SetHTMLOptions$I %options = {}); [`CEReactions$] `undefined$ `setHTML$m(`DOMString$ %html, optional `SetHTMLOptions$I %options = {}); };
`Element$I 上に定義された~methodは、 `ShadowRoot$I 上にも定義される: ◎ These methods are mirrored on the ShadowRoot:
`ShadowRoot$I の `setHTMLUnsafe(html, options)@m ~method手続きは: ◎ ShadowRoot's setHTMLUnsafe(html, options) method steps are:
- %準拠~HTML ~LET `信用-済みな型に準拠な文字列を取得する$( ↓ ) ⇒# `TrustedHTML$I, コレに`関連な大域~obj$, %html, `ShadowRoot setHTMLUnsafe^l, `script^l ◎ 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".
- `~HTMLを設定して~filterする$( ↓ ) ⇒# コレ, コレの`~shadow~host$, %準拠~HTML, %options, ~F ◎ Set and filter HTML using this, this's shadow host (as context element), compliantHTML, options, and false.
`ShadowRoot$I の `setHTML(html, options)@m ~method手続きは: ◎ ShadowRoot's setHTML(html, options) method steps are:
- `~HTMLを設定して~filterする$( ↓ ) ⇒# コレ, コレ, %html, %options, ~T ◎ Set and filter HTML using this (as target), this (as context element), html, options, and true.
`Document$I ~interfaceには、 2 つの新たな静的~methodが定義される — それは、 所与の文字列を `Document$I 全体を成すものとして構文解析する: ◎ The Document interface gains two new methods which parse an entire Document:
partial interface `Document$I { static `Document$I `parseHTMLUnsafe$m((`TrustedHTML$ or `DOMString$) %html, optional `SetHTMLOptions$I %options = {}); static `Document$I `parseHTML$m(`DOMString$ %html, optional `SetHTMLOptions$I %options = {}); };
`parseHTMLUnsafe(html, options)@m ~method手続きは: ◎ The parseHTMLUnsafe(html, options) method steps are:
- %準拠~HTML ~LET `信用-済みな型に準拠な文字列を取得する$( ↓ ) ⇒# `TrustedHTML$I, コレに`関連な大域~obj$, %html, `Document parseHTMLUnsafe^l, `script^l ◎ 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".
-
%文書 ~LET 新たな `Document$I — その ⇒# `内容~型$doc ~SET `text/html^l ◎ Let document be a new Document, whose content type is "text/html".
注記: %文書 が`属する閲覧~文脈$は ~NULL なので、 ~scriptingは不能化される。 ◎ Note: Since document does not have a browsing context, scripting is disabled.
- %文書 の`宣言的な~shadow根を許容するか$doc ~SET ~T ◎ Set document’s allow declarative shadow roots to true.
- `文字列から~HTMLを構文解析する$( %文書, %準拠~HTML ) ◎ Parse HTML from a string given document and compliantHTML.
- %環境設定0 ~LET `~option群から無毒化器~環境設定0を取得する$( %options, ~F ) ◎ Let config be the result of calling get a sanitizer config from options with options and false.
- ~IF[ %環境設定0 は`空$map【!`空$】でない ] ⇒ `~nodeを無毒化する$( %文書 の`根~node$, %環境設定0 ) ◎ If config is not empty, then call sanitize on document’s root node with config.
- ~RET %文書 ◎ Return document.
`parseHTML(html, options)@m ~method手続きは: ◎ The parseHTML(html, options) method steps are:
-
%文書 ~LET 新たな `Document$I — その ⇒# `内容~型$doc ~SET `text/html^l ◎ Let document be a new Document, whose content type is "text/html".
注記: %文書 が`属する閲覧~文脈$は ~NULL なので、 ~scriptingは不能化される。 ◎ Note: Since document does not have a browsing context, scripting is disabled.
- %文書 の`宣言的な~shadow根を許容するか$doc ~SET ~T ◎ Set document’s allow declarative shadow roots to true.
- `文字列から~HTMLを構文解析する$( %文書, %html ) ◎ Parse HTML from a string given document and html.
- %環境設定0 ~LET `~option群から無毒化器~環境設定0を取得する$( %options, ~T ) ◎ Let config be the result of calling get a sanitizer config from options with options and true.
- `~nodeを無毒化する$( %文書 の`根~node$, %環境設定0 ) ◎ Call sanitize on document’s root node with config.
- ~RET %文書 ◎ Return document.
2.2. `SetHTML^I ~option群と環境設定~obj
`setHTML()$mE に類する~methodは、 いずれも,ある~option群を与える辞書を受容する。 今の所は、 この辞書に定義される~memberは 1 つしかない: ◎ The family of setHTML()-like methods all accept an options dictionary. Right now, only one member of this dictionary is defined:
dictionary `SetHTMLOptions@I { (`Sanitizer$I or `SanitizerConfig$I) `sanitizer@mb = {}; };
`Sanitizer$I 環境設定~objは、 ~filter環境設定を~capsule化する。 同じ環境設定0を[ 安全な~method/安全でない~method ] 【 `…HTML()^c/ `…HTMLUnsafe()^c 】 どちらでも利用できる。 その意図は、 ~pageの存続期間における早期に少数の環境設定を築いておいて, 必要に応じて利用できるようにすることである。 これは、 それらの環境設定を予め処理することを実装に許容する。 ◎ The Sanitizer configuration object encapsulates a filter configuration. The same config can be used with both safe or unsafe methods. 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.
環境設定~objは、 ~query可能であり,[ 安全な変種/安全でない変種 ] 【 `get()$m/ `getUnsafe()$m 】 どちらにおいても`正準的な環境設定$~辞書を返せる。 これは、 次を~pageに許容する ⇒# 所与の環境設定による効果を~queryして予測する。 既存のそれに基づいて新たな環境設定を築く。 ◎ The configuration object is also query-able and can return canonical 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.
[`Exposed$=(Window,Worker)] interface `Sanitizer@I { `constructor@#dom-sanitizer-sanitizer$(optional `SanitizerConfig$I %config = {}); `SanitizerConfig$I `get$m(); `SanitizerConfig$I `getUnsafe$m(); };
各 `Sanitizer$I ~objは、 `config@sl `内部~slot$を有する — それは、 `SanitizerConfig$I 辞書であり, 作成-時に設定される。 ◎ ↓
2.3. 環境設定~辞書
dictionary `SanitizerElementNamespace@I {
required `DOMString$ `name@mbE;
`DOMString$? _`namespace@mbE = "http://www.w3.org/1999/xhtml";
};
/*
"`elements$mb" により利用される
◎
Used by "elements"
*/
dictionary `SanitizerElementNamespaceWithAttributes@I : `SanitizerElementNamespace$I {
`sequence$<`SanitizerAttribute$I> `attributes@mbE;
`sequence$<`SanitizerAttribute$I> `removeAttributes@mbE;
};
typedef (`DOMString$ or `SanitizerElementNamespace$I) `SanitizerElement@I;
typedef (`DOMString$ or `SanitizerElementNamespaceWithAttributes$I) `SanitizerElementWithAttributes@I;
dictionary `SanitizerAttributeNamespace@I {
required `DOMString$ `name@mbA;
`DOMString$? _`namespace@mbA = null;
};
typedef (`DOMString$ or `SanitizerAttributeNamespace$I) `SanitizerAttribute@I;
dictionary `SanitizerConfig@I {
`sequence$<`SanitizerElementWithAttributes$I> `elements@mb;
`sequence$<`SanitizerElement$I> `removeElements@mb;
`sequence$<`SanitizerElement$I> `replaceWithChildrenElements@mb;
`sequence$<`SanitizerAttribute$I> `attributes@mb;
`sequence$<`SanitizerAttribute$I> `removeAttributes@mb;
`boolean$ `comments@mb;
`boolean$ `dataAttributes@mb;
};
3. ~algo
`~HTMLを設定して~filterする@ ときは、 所与の ⇒# [ `Element$I / `DocumentFragment$I ] %~target, `Element$I %文脈~要素, `文字列$ %html, `辞書$ %~option群, `真偽値$ %安全か ◎終 に対し: ◎ To set and filter HTML, given an Element or DocumentFragment target, an Element contextElement, a string html, and a dictionary options, and a boolean safe:
- ~IF[ %安全か ~EQ ~T ]~AND[ %文脈~要素 の`局所-名$ ~EQ `script^l ]~AND[ %文脈~要素 の`名前空間$ ~IN { `~HTML名前空間$, `~SVG名前空間$ } ] ⇒ ~RET ◎ If safe and contextElement’s local name is "script" and contextElement’s namespace is the HTML namespace or the SVG namespace, then return.
- %環境設定0 ~LET `~option群から無毒化器~環境設定0を取得する$( %~option群, %安全か ) ◎ Let config be the result of calling get a sanitizer config from options with options and safe.
-
%新たな子~群 ~LET `素片を構文解析する$( %文脈~要素, %html, ~T )
【 3 個目の引数 ~T は余計 — `~HTML素片の構文解析~algo@~HTMLparsing#html-fragment-parsing-algorithm$であったなら合致するが。 】
◎ Let newChildren be the result of the HTML fragment parsing algorithm steps given contextElement, html, and true. - %素片 ~LET 新たな `DocumentFragment$I — その ⇒# `~node文書$ ~SET %文脈~要素 の`~node文書$ ◎ Let fragment be a new DocumentFragment whose node document is contextElement’s node document.
- %新たな子~群 を成す ~EACH( %~node ) に対し ⇒ %素片 【の`子~群$】に %~node を`付加する$ ◎ For each node in newChildren, append node to fragment.
- ~IF[ %環境設定0 は`空$map【!`空$】でない ] ⇒ `~nodeを無毒化する$( %素片, %環境設定0 ) ◎ If config is not empty, then run sanitize on fragment using config.
- %~target の`全~内容を~nodeで置換する$( %素片 ) ◎ Replace all with fragment within target.
`~option群から無毒化器~環境設定0を取得する@ ときは、 所与の ( %~option群, 真偽値 %安全か ) に対し: ◎ To get a sanitizer config from options for an options dictionary options and a boolean safe, do:
- ~Assert: %~option群 は`辞書$である。 ◎ Assert: options is a dictionary.
- %環境設定0 ~LET %~option群[ `sanitizer^l ] ◎ ↓
- ~IF[ %環境設定0 ~EQ ε ] ⇒ ~RET `undefined^en 【空な `SanitizerConfig$I を返すべきであろう(さもなければ他所と一貫しない)】 ◎ If options["sanitizer"] doesn’t exist, then return undefined.
- ~Assert: %環境設定0 は[ `Sanitizer$I ~instance/`辞書$ ]である。 ◎ Assert: options["sanitizer"] is either a Sanitizer instance or a dictionary.
- ~IF[ %環境設定0 は `Sanitizer$I ~instanceである ] ⇒ %環境設定0 ~LET %環境設定0.`config$sl ◎ If options["sanitizer"] is a Sanitizer instance: • Then let config be the value of options["sanitizer"]'s internal slot. • Otherwise let config be the value of options["sanitizer"].
- ~RET `環境設定を正準-化する$( %環境設定0, %安全か ) ◎ Return the result of calling canonicalize a configuration on config and safe.
3.1. 無毒化~algo
`~nodeを無毒化する@ ときは、 所与の ( `ParentNode$I %~node, `SanitizerConfig$I %環境設定0 ) に対し,次の手続きを走らす: ◎ For the main sanitize operation, using a ParentNode node, a canonical SanitizerConfig config, run these steps:
- ~Assert: %環境設定0 は`正準的な環境設定$である ◎ Assert: config is canonical.
- %elements ~LET %環境設定0[ "`elements$mb" ] ◎ ↓
- %現在の~node ~LET %~node ◎ Let current be node.
-
%現在の~node の`子~群$を成す ~EACH( %子 ) に対し: ◎ For each child in current’s children:
-
~Assert: %子 は次に挙げるいずれかを`実装-$する ⇒ `Text$I / `Comment$I / `Element$I ◎ Assert: child implements Text, Comment, or Element.
注記: この~algoに渡される %~node は、 現時点では,~HTML構文解析器の出力に限られ、 この表明は,それに対しては満たされるべきである。 この~algoが将来に異なる文脈にて利用されるようになった場合、 この前提は,精査し直す必要がある。 ◎ Note: Currently, this algorithm is only called on output of the HTML parser for which this assertion should hold. If in the future this algorithm will be used in different contexts, this assumption needs to be re-examined.
- ~IF[ %子 は `Text$I を`実装-$する ] ⇒ ~CONTINUE ◎ If child implements Text: • continue.
-
~IF[ %子 は `Comment$I を`実装-$する ]:
- ~IF[ %環境設定0[ "`comments$mb" ] ~NEQ ~T ] ⇒ `~nodeを除去する$( %子 )
- ~CONTINUE
- %要素~名 ~LET «[ "`name$mbE" → %子 の`局所-名$, "`namespace$mbE" → %子 の`名前空間$ ]» 【!新たな `SanitizerElementNamespace$I】 ◎ Let elementName be a SanitizerElementNamespace with child’s local name and namespace.
-
~IF[ ~OR↓ ]…
- [ %elements ~NEQ ε ]~AND[ %要素~名 ~NIN `名前$sub %elements ]
- [ %環境設定0[ "`removeElements$mb" ] ~NEQ ε ]~AND[ %要素~名 ~IN `名前$sub %環境設定0[ "`removeElements$mb" ] ]
…ならば ⇒ `~nodeを除去する$( %子 )
◎ If config["elements"] exists and config["elements"] does not contain [elementName]: • remove child. ◎ else if config["removeElements"] exists and config["removeElements"] contains [elementName]: • remove child. -
~IF[ %環境設定0[ "`replaceWithChildrenElements$mb" ] ~NEQ ε ]~AND[ %要素~名 ~IN `名前$sub %環境設定0[ "`replaceWithChildrenElements$mb" ] ]: ◎ If config["replaceWithChildrenElements"] exists and config["replaceWithChildrenElements"] contains elementName:
- `~nodeを無毒化する$( %子, %環境設定0 ) ◎ Call sanitize on child with config.
- %子 の`全~内容を~nodeで置換する$( %子 の`子~群$ ) 【意図不明な演算(引数の型も合致していない)】 ◎ Call replace all with child’s children within child.
- ~IF[ %要素~名[ "`name$mbE" ] ~EQ `template^l ]~AND[ %要素~名[ "`namespace$mbE" ] ~EQ `~HTML名前空間$ 【!%要素~名 `同等な集合$ «[ `name^l → `template^l, `namespace^l → `~HTML名前空間$ ]»】 ] ⇒ `~nodeを無毒化する$( %子 の`~template内容$, %環境設定0 ) ◎ If elementName equals «[ "name" → "template", "namespace" → HTML namespace ]» • Then call sanitize on child’s template contents with config.
- ~IF[ %子 は`~shadow~host$である ] ⇒ `~nodeを無毒化する$( %子 の`~shadow根$el, %環境設定0 ) ◎ If child is a shadow host: • Then call sanitize on child’s shadow root with config.
-
%現在の~node の`属性~list$を成す ~EACH( %属性 ) に対し: ◎ For each attr in current’s attribute list:
- %属性~名 ~LET «[ "`name$mbA" → %属性 の`局所-名$attr, "`namespace$mbA" → %属性 の`名前空間$attr ]» 【!新たな `SanitizerAttributeNamespace$I】 ◎ Let attrName be a SanitizerAttributeNamespace with attr’s local name and namespace.
- %A ~LET ~IS[ %環境設定0[ "`attributes$mb" ] ~NEQ ε ]~AND[ %属性~名 ~NIN`名前$sub %環境設定0[ "`attributes$mb" ] ] ◎ ↓
-
~IF[ ~OR↓ ]…
-
~AND↓:
- %A ~EQ ~T
- `data-^l は`局所-名$attrの`符号単位~接頭辞$である
- `名前空間$attr ~EQ ~NULL
- %環境設定0[ "`dataAttributes$mb" ] ~EQ ~F
-
~AND↓:
- %A ~EQ ~F
- %環境設定0[ "`removeAttributes$mb" ] ~NEQ ε
- %属性~名 ~IN `名前$sub %環境設定0[ "`removeAttributes$mb" ]
-
~AND↓:
- %elements[ %要素~名 ] ~NEQ ε
- %elements[ %要素~名 ][ "`attributes$mbE" ] ~NEQ ε
- %属性~名 ~NIN `名前$sub %elements[ %要素~名 ][ "`attributes$mbE" ]
-
~AND↓:
- %elements[ %要素~名 ]~NEQ ε
- %elements[ %要素~名 ][ "`removeAttributes$mbE" ] ~NEQ ε
- %属性~名 ~IN `名前$sub %elements[ %要素~名 ][ "`removeAttributes$mbE" ]
-
~AND↓:
- { %要素~名, %属性~名 } は、 `~navigate用の~URL属性~list$を成す ある~entryに合致する
- %属性 の `protocol@~URLPATTERN#constructor-string-parser-state-protocol$ ~EQ `javascript:^l 【この条件は、いくぶん曖昧である(~link先も正しいのか疑わしい)】
…ならば ⇒ %子 から %属性 を除去する
-
- `~nodeを無毒化する$( %子 の`~shadow根$el, %環境設定0 ) ◎ Call sanitize on child’s shadow root with config.
- ~ELSE【どの条件を参照するのか不明】 ⇒ `~nodeを除去する$( %子 ) ◎ else: • remove child.
-
3.2. 環境設定の処理-法
%環境設定0 は `妥当な環境設定@ であるとは、 次を遂行した結果 ~EQ ~T になることをいう: ◎ A config is valid if all these conditions are met:
- ~IF[ %環境設定0 は`辞書$でない ] ⇒ ~RET ~F ◎ config is a dictionary
- 【!does not contain both】 ~IF[ %環境設定0[ "`elements$mb" ] ~NEQ ε ]~AND[ %環境設定0[ "`removeElements$mb" ] ~NEQ ε ] ⇒ ~RET ~F ◎ config’s key set does not contain both "elements" and "removeElements"
- 【!does not contain both】 ~IF[ %環境設定0[ "`attributes$mb" ] ~NEQ ε ]~AND[ %環境設定0[ "`removeAttributes$mb" ] ~NEQ ε ] ⇒ ~RET ~F ◎ config’s key set does not contain both "removeAttributes" and "attributes".
- %~key群 ~LET « "`elements$mb", "`removeElements$mb", "`replaceWithChildrenElements$mb", "`attributes$mb", "`removeAttributes$mb" » ◎ ↓
- %~key群 を成す ~EACH( %~key ) に対し ⇒ ~IF[ %環境設定0[ %~key ] ~NEQ ε ]~AND[ %環境設定0[ %~key ] は`妥当な名前~list$でない ] ⇒ ~RET ~F ◎ For any key of «[ "elements", "removeElements", "replaceWithChildrenElements", "attributes", "removeAttributes" ]» where config[key] exists: • config[key] is valid.
-
~IF[ %環境設定0[ "`elements$mb" ] ~NEQ ε ]: ◎ If config["elements"] exists,\
-
%環境設定0[ "`elements$mb"【! [ %~key ]】 ] を成す ~EACH( %要素 ) に対し: ◎ then for any element in config[key]\
- ~IF[ %要素 は`辞書$でない ] ⇒ ~CONTINUE ◎ that is a dictionary:
- 【!does not contain】 ~IF[ %要素[ "`attributes$mbE" ] ~NEQ ε ]~AND[ %要素[ "`removeAttributes$mbE" ] ~NEQ ε ] ⇒ ~RET ~F ◎ element does not contain both "attributes" and "removeAttributes".
- « "`attributes$mbE", "`removeAttributes$mbE" » を成す ~EACH( %~key ) に対し ⇒ ~IF[ %要素[ %~key ] ~NEQ ε ]~AND[ %要素[ %~key ] は`妥当な名前~list$でない ] ⇒ ~RET ~F ◎ If either element["attributes"] or element["removeAttributes"] exists, then it is valid.
【 原文では、 以降の段もこの~loopの中で遂行されているが,誤りであろう。 】
-
- %tmp ~LET 新たな`有順序~map$【!`辞書$】 ◎ Let tmp be a dictionary,\
-
%~key群 を成す ~EACH( %~key ) に対し:
- %~list ~LET %環境設定0[ %~key ]
-
~IF[ %~list ~EQ ε ] ⇒ %~list ~SET 新たな`~list$
【 この段は、 この訳による補完。 】
- %名前空間 ~LET ~NULL
- ~IF[ %~key ~IN { "`elements$mb", "`removeElements$mb", "`replaceWithChildrenElements$mb" } ] ⇒ %名前空間 ~SET `~HTML名前空間$
- %tmp[ %~key ] ~SET `無毒化器~用の~listを正準-化する$( %~list, %名前空間 )
注記: 上で正準-化する意図は、[ 文字列/明示的な辞書 【!the string shortcut syntax or the explicit dictionary syntax】 ]どちらが利用されるかを問わず, ~listを成す~item【!list elements】について表明することにある。 例えば, `elements^c 内に `img^l があって `removeElements^c 内に `{ name: "img" }^c があるとき。 実装は、 この時点で~listを明示的に正準-化することなく, これをきちんと行うこともできよう。 ◎ Note: The intent here is to assert about list elements, but without regard to whether the string shortcut syntax or the explicit dictionary syntax is used. For example, having "img" in elements and { name: "img" } in removeElements. An implementation might well do this without explicitly canonicalizing the lists at this point.
-
~IF[ 次に挙げる集合のうち,`空$でないものがある ]… ◎ Given theses canonicalized name lists, all of the following conditions hold:
- `交差集合$( %tmp[ `elements^l ], %tmp[ `removeElements^l ] ) ◎ The intersection between tmp["elements"] and tmp["removeElements"] is empty.
- `交差集合$( %tmp[ `removeElements^l ], %tmp[ `replaceWithChildrenElements^l ] ) ◎ The intersection between tmp["removeElements"] tmp["replaceWithChildrenElements"] is empty.
- `交差集合$( %tmp[ `replaceWithChildrenElements^l ], %tmp[ `elements^l ] ) ◎ The intersection between tmp["replaceWithChildrenElements"] and tmp["elements"] is empty.
- `交差集合$( %tmp[ `attributes^l ], %tmp[ `removeAttributes^l ] ) ◎ The intersection between tmp["attributes"] and tmp["removeAttributes"] is empty.
…ならば ⇒ ~RET ~F
- %tmpattrs ~LET %tmp[ `attributes^l ] ◎ Let tmpattrs be tmp["attributes"]\
- ~IF[ %環境設定0[ "`attributes$mb" ] ~EQ ε ] ⇒ %tmpattrs ~SET `組込みの既定の環境設定0$[ "`attributes$mb" ] ◎ if it exists, and otherwise built-in default config["attributes"].
- %tmp[ `elements^l ] を成す ~EACH( %~item ) に対し ⇒ « "`attributes$mbE", "`removeAttributes$mbE" » を成す ~EACH( %~key ) に対し ⇒ ~IF[ %~item[ %~key ] ~NEQ ε ]~AND[ `差集合$( %~item[ %~key ], %tmpattrs ) は`空$でない ] ⇒ ~RET ~F ◎ For any item in tmp["elements"]: • If either item["attributes"] or item["removeAttributes"] exists: •• Then the difference between it and tmpattrs is empty.
- ~RET ~T
所与の %~list が `妥当な名前~list@ であるとは、 ~AND↓ が満たされることをいう: ◎ A list of names is valid if all these conditions are met:
- %~list は`~list$である ◎ list is a list.
-
%~list を成す どの %名前 も ~OR↓ を満たす: ◎ For all of its members name:
- %名前 は`文字列$である ◎ name is a string or a dictionary.
- [ %名前 は`辞書$である ]~AND[ 【!%名前[ "`name$mbE" ] ~NEQ ε]~AND[】 %名前[ "`name$mbE" ] は`文字列$である ] ◎ If name is a dictionary: • name["name"] exists and is a string.
所与の %環境設定0 が `正準的な環境設定@ であるとは、 ~AND↓ が満たされることをいう: ◎ A config is canonical if all these conditions are met:
- %環境設定0 は`妥当な環境設定$である ◎ config is valid.
-
%環境設定0 の`~key群$map %~key群 は ~AND↓ を満たす ◎ ↓
- 次の`下位集合$である ⇒ { "`elements$mb", "`removeElements$mb", "`replaceWithChildrenElements$mb", "`attributes$mb", "`removeAttributes$mb", "`comments$mb", "`dataAttributes$mb" } ◎ config’s key set is a subset of «[ "elements", "removeElements", "replaceWithChildrenElements", "attributes", "removeAttributes", "comments", "dataAttributes" ]»
-
~OR↓: ◎ config’s key set contains either:
-
~AND↓:
- "`elements$mb" ~IN %~key群
- "`attributes$mb" ~IN %~key群
- "`removeElements$mb" ~NIN %~key群
- "`removeAttributes$mb" ~NIN %~key群
-
~AND↓:
- "`elements$mb" ~NIN %~key群
- "`attributes$mb" ~NIN %~key群
- "`removeElements$mb" ~IN %~key群
- "`removeAttributes$mb" ~IN %~key群
-
- どの %~key ~IN { "`replaceWithChildrenElements$mb", "`removeElements$mb", "`attributes$mb", "`removeAttributes$mb" } に対しても,次が満たされる ⇒ [ %環境設定0[ %~key ] ~EQ ε ]~OR[ %環境設定0[ %~key ] は`正準的な名前~list$である ] ◎ For any key of «[ "replaceWithChildrenElements", "removeElements", "attributes", "removeAttributes" ]» where config[key] exists: • config[key] is canonical.
- [ %環境設定0[ "`elements$mb" ] ~EQ ε ]~OR[ %環境設定0[ "`elements$mb" ] は`属性も込みで正準的な名前~list$である ] ◎ If config["elements"] exists: • config["elements"] is canonical.
- どの %~key ~IN { "`comments$mb", "`dataAttributes$mb" } に対しても,次が満たされる ⇒ [ %環境設定0[ %~key ] ~EQ ε ]~OR[ %環境設定0[ %~key ] は`真偽値$【!`boolean$】である ] ◎ For any key of «[ "comments", "dataAttributes" ]»: • if config[key] exists, config[key] is a boolean.
所与の %~list が `正準的な名前~list@ であるとは、 ~AND↓ が満たされることをいう: ◎ A list of names is canonical if all these conditions are met:
- %~list【!list[key]】 は`~list$である ◎ list[key] is a list.
-
%~list【!list[key]】 を成す どの %名前 も ~AND↓ を満たす: ◎ For all of its list[key]'s members name:
- %名前 は`辞書$である ◎ name is a dictionary.
- [ %名前 の`~key群$map, « "`name$mbE", "`namespace$mbE" » ]は`同等な集合$である ◎ name’s key set equals «[ "name", "namespace" ]»
- %名前[ "`name$mbE" ] は`文字列$である ◎ ↓
- %名前[ "`namespace$mbE" ] は`文字列$である ◎ name’s values are strings.
所与の %~list が `属性も込みで正準的な名前~list@ であるとは、 ~AND↓ が満たされることをいう: ◎ A list of names is canonical if all these conditions are met:
- %~list【!list[key]】 は`~list$である ◎ list[key] is a list.
-
%~list【!list[key]】 を成す どの %名前 も ~AND↓ を満たす: ◎ For all of its list[key]'s members name:
- %名前 は`辞書$である ◎ name is a dictionary.
-
%名前 の`~key群$mapは、 次に挙げるいずれかと`同等な集合$である: ◎ name’s key set equals one of:
- « "`name$mbE", "`namespace$mbE" » ◎ «[ "name", "namespace" ]»
- « "`name$mbE", "`namespace$mbE", "`attributes$mbE" » ◎ «[ "name", "namespace", "attributes" ]»
- « "`name$mbE", "`namespace$mbE", "`removeAttributes$mbE" » ◎ «[ "name", "namespace", "removeAttributes" ]»
- %名前[ "`name$mbE" ] は`文字列$である ◎ ↓
- %名前[ "`namespace$mbE" ] は`文字列$である ◎ name["name"] and name["namespace"] are strings.
- [ %名前[ "`attributes$mbE" ] ~EQ ε ]~OR[ %名前[ "`attributes$mbE" ] は`正準的な名前~list$である ] ◎ ↓
- [ %名前[ "`removeAttributes$mbE" ] ~EQ ε ]~OR[ %名前[ "`removeAttributes$mbE" ] は`正準的な名前~list$である ] ◎ name["attributes"] and name["removeAttributes"] are canonical if they exist.
`環境設定を正準-化する@ ときは、 所与の ( %環境設定0, `真偽値$ %安全か ) に対し: ◎ To canonicalize a configuration config with a boolean safe:
注記: 始めの方にある各 ~Assert は、[ `§ 既定@#sanitization-defaults$ に述べられる組込みの各種~既定 ]の特質を表明する。 ◎ Note: The initial set of asserts assert properties of the built-in constants, like the defaults and the lists of known elements and attributes.
- ~Assert: `組込みの既定の環境設定0$は`正準的な環境設定$である。 ◎ Assert: built-in default config is canonical.
- ~Assert: `組込みの既定の環境設定0$[ `elements^l ] は`既知な要素~群$の`下位集合$である。 ◎ Assert: built-in default config["elements"] is a subset of known elements.
- ~Assert: `組込みの既定の環境設定0$[ `attributes^l ] は`既知な属性~群$の`下位集合$である。 ◎ Assert: built-in default config["attributes"] is a subset of known attributes.
- ~Assert: «[ `elements^l → `既知な要素~群$, `attributes^l → `既知な属性~群$ ]» は`正準的な環境設定$である。 ◎ Assert: «[ "elements" → known elements, "attributes" → known attributes, ]» is canonical.
- %結果 ~LET 新たな`辞書$ ◎ ↓
- ~IF[ %環境設定0 は`空$map【!`空$】である ]~AND[ %安全か ~EQ ~F ] ⇒ ~RET %結果【!«[]»】 ◎ If config is empty and not safe, then return «[]»
- ~IF[ %環境設定0 は`妥当な環境設定$でない ] ⇒ ~THROW `TypeError$E ◎ If config is not valid, then throw a TypeError. ◎ ↑ Let result be a new dictionary.
-
« "`elements$mb", "`removeElements$mb", "`replaceWithChildrenElements$mb", "`attributes$mb", "`removeAttributes$mb" » を成す ~EACH( %~key ) に対し:
- %~list ~LET %環境設定0[ %~key ]
- ~IF[ %~list ~EQ ε ] ⇒ ~CONTINUE
- %名前空間 ~LET ~NULL
- ~IF[ %~key ~IN { "`elements$mb", "`removeElements$mb", "`replaceWithChildrenElements$mb" } ] ⇒ %名前空間 ~SET `~HTML名前空間$
- %結果[ %~key ] ~SET `無毒化器~用の~listを正準-化する$( %~list, %名前空間 )
- %結果[ "`comments$mb" ] ~SET %環境設定0[ "`comments$mb" ] ◎ Set result["comments"] to config["comments"].
- %既定 ~LET `環境設定を正準-化する$( `組込みの既定の環境設定0$ ) ◎ Let default be the result of canonicalizing a configuration for the built-in default config.
-
~IF[ %安全か ~EQ ~T ]: ◎ If safe:
-
~IF[ %環境設定0[ "`elements$mb" ] ~NEQ ε ]: ◎ If config["elements"] exists:
-
%要素~阻止-~list ~LET `差集合$( `既知な要素~群$, %既定[ "`elements$mb" ] ) ◎ Let elementBlockList be the difference between known elements default["elements"].
注記: 交差集合をとる方が,既定の要素~listを施行するには “自然” な仕方だが、 そうすると,未知なもの (すなわち、 `foo^e の様な,~HTMLからは給されない要素) を排することになる。 なので、 “安全でない” 要素を取り除くために利用-可能な “阻止-~list” として構築する。 ◎ 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.
- %結果[ "`elements$mb" ] ~SET `差集合$( %結果[ "`elements$mb" ], %要素~阻止-~list ) ◎ Set result["elements"] to the difference of result["elements"] and elementBlockList.
-
-
~IF[ %環境設定0[ "`removeElements$mb" ] ~NEQ ε ]: ◎ If config["removeElements"] exists:
- %結果[ "`elements$mb" ] ~SET `差集合$( %既定[ "`elements$mb" ], %結果[ "`removeElements$mb" ] ) ◎ Set result["elements"] to the difference of default["elements"] and result["removeElements"].
- %結果[ "`removeElements$mb" ] ~SET ε【!を`除去する$】 ◎ Remove "removeElements" from result.
- ~IF[ %環境設定0[ "`elements$mb" ] ~EQ ε ]~AND[ %環境設定0[ "`removeElements$mb" ] ~EQ ε ] ⇒ %結果[ "`elements$mb" ] ~SET %既定[ "`elements$mb" ] ◎ If neither config["elements"] nor config["removeElements"] exist: • Set result["elements"] to default["elements"].
-
~IF[ %環境設定0[ "`attributes$mb" ] ~NEQ ε ]: ◎ If config["attributes"] exists:
- %属性~阻止-~list ~LET `差集合$( `既知な属性~群$, %既定[ "`attributes$mb" ] ) ◎ Let attributeBlockList be the difference between known attributes and default["attributes"];
- %結果[ "`attributes$mb" ] ~SET `差集合$( %結果[ "`attributes$mb" ], %属性~阻止-~list ) ◎ Set result["attributes"] to the difference of result["attributes"] and attributeBlockList.
-
~IF[ %環境設定0[ "`removeAttributes$mb" ] ~NEQ ε ]: ◎ If config["removeAttributes"] exists:
- %結果[ "`attributes$mb" ] ~SET `差集合$( %既定[ "`attributes$mb" ], %結果[ "`removeAttributes$mb" ] ) ◎ Set result["attributes"] to the difference of default["attributes"] and result["removeAttributes"].
- %結果[ "`removeAttributes$mb" ] ~SET ε【!`除去する$】 ◎ Remove "removeAttributes" from result.
-
~IF[ %環境設定0[ "`attributes$mb" ] ~EQ ε ]~AND[ %環境設定0[ "`removeAttributes$mb" ] ~EQ ε ] ⇒ %結果[ "`attributes$mb" ] ~SET %既定[ "`attributes$mb" ] ◎ If neither config["attributes"] nor config["removeAttributes"] exist: • Set result["attributes"] to default["attributes"].
-
-
~ELSE( %安全か ~EQ ~F ): ◎ Else (if not safe):
- ~IF[ %環境設定0[ "`elements$mb" ] ~EQ ε ]~AND[ %環境設定0[ "`removeElements$mb" ] ~EQ ε ] ⇒ %結果[ "`elements$mb" ] ~SET %既定[ "`elements$mb" ] ◎ If neither config["elements"] nor config["removeElements"] exist: • Set result["elements"] to default["elements"].
- ~IF[ %環境設定0[ "`attributes$mb" ] ~EQ ε ]~AND[ %環境設定0[ "`removeAttributes$mb" ] ~EQ ε ] ⇒ %結果[ "`attributes$mb" ] ~SET %既定[ "`attributes$mb" ] ◎ If neither config["attributes"] nor config["removeAttributes"] exist: • Set result["attributes"] to default["attributes"].
- ~Assert: %結果 は`正準的な環境設定$である。 ◎ (不要)Assert: result is valid. ◎ Assert: result is canonical.
- ~RET %結果 ◎ Return result.
`無毒化器~用の~listを正準-化する@ ときは、 所与の ( %~list, %既定の名前空間 ) に対し: ◎ In order to canonicalize a sanitizer element list list, with a default namespace defaultNamespace, run the following steps:
- %結果 ~LET 新たな`有順序~集合$ ◎ Let result be a new ordered set.
- %~list を成す ~EACH( %名前 ) に対し ⇒ %結果 に次の結果を`付加する$set ⇒ `無毒化器~用の名前を正準-化する$( %名前, %既定の名前空間 ) ◎ For each name in list, call canonicalize a sanitizer name on name with defaultNamespace and append to result.
- ~RET %結果 ◎ Return result.
`無毒化器~用の名前を正準-化する@ ときは、 所与の ( %名前, %既定の名前空間 ) に対し:
- ~Assert: %名前 は[ `文字列$ /`辞書$ ]である。
- %名前~空間 ~LET %既定の名前空間
-
~IF[ %名前 は`辞書$である ]:
- ~IF[ %名前[ `namespace^l ] ~NEQ ε ] ⇒ %名前~空間 ~SET %名前[ `namespace^l ]
- %名前 ~SET %名前[ `name^l ]
- ~Assert: %名前 ~NEQ ε
- ~RET «[ `name^l → %名前, `namespace^l → %名前空間 ]»
3.3. ~support用の~algo
この仕様において利用される`正準-化された@#canonicalize-a-sanitizer-name$[ 要素~名( `SanitizerElementNamespace$I ) / 属性~名( `SanitizerAttributeNamespace$I ) ]たちが成す~list用には、 ~listの~memberであるか否かは,[ `name^l, `namespace^l ]両~entryを照合すること(`同等な名前$か否か)に基づく。 ◎ For the canonicalized element and attribute name lists used in this spec, list membership is based on matching both "name" and "namespace" entries:\
所与の ( %A, %B ) が `同等な名前@ であるとは、 ~AND↓ が満たされることをいう:
- %A は`有順序~map$である
- %B は`有順序~map$である
- %A[ `name^l ] ~EQ %B[ `name^l ]
- %A[ `namespace^l ] ~EQ %B[ `namespace^l ]
この条件は、[ %A ~EQ`名前$sub %B ]とも表記される (その否定は ~NEQ`名前$sub )。 ~item %A が[ `有順序~集合$/`~list$ ] %L に包含されることを表す条件は、[ %A ~IN`名前$sub %L ]のように表記される。
【 この用語は、 原文では,[ ある種の集合に属するための条件 ]として定義されているが、 この訳では, 集合に包含され得る~itemどうしの同等性として定義し直す。 集合に対する汎用な演算(`付加する$set, `交差集合$など)は、 暗黙的に,~itemどうしの同等性に基づくので。 】
◎ 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 item["namespace"] equals entry["namespace"].`差集合@ を算出するときは、 所与の ( `有順序~集合$ %A, `有順序~集合$ %B ) に対し: ◎ 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:
- %集合 ~LET 新たな`有順序~集合$ ◎ Let set be a new ordered set.
- %A を成す ~EACH( %~item ) に対し: ⇒ ~IF[ %~item ~NIN %B ] ⇒ %集合 に %~item を`付加する$set ◎ For each item of A: • If B does not contain item, then append item to set.
- ~RET %集合 ◎ Return set.
`有順序~集合$どうしの同等性は、 順序を問わずに,それを成す各~itemどうしの同等性に基づく。 `有順序~集合$ %A, %B が `同等な集合@ であるとは、 次を満たすことをいう ⇒ [ %A は %B の`上位集合$である ]~AND[ %B は %A の`上位集合$である ] ◎ 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.
3.4. 既定
注記: 各~既定は、 ある種の形に従うべきものであり, `環境設定を正準-化する$ときの始めの方で検査される。 ◎ Note: The defaults should follow a certain form, which is checked for at the beginning of canonicalize a configuration.
`組込みの既定の環境設定0@ は、 次の様な形で与えられる: ◎ The built-in default config is as follows:
{ elements: [....], attributes: [....], comments: true, }
【 `~key$mapとして[ `elements^l, `attributes^l, `comments^l ]を伴う`有順序~map$。 】
`既知な要素~群@ は、 次の様な形で与えられる: ◎ The known elements are as follows:
[ { name: "div", namespace: "http://www.w3.org/1999/xhtml" }, ... ]
`既知な属性~群@ は、 次の様な形で与えられる: ◎ The known attributes are as follows:
[ { name: "class", namespace: null }, ... ]
注記: [ `既知な要素~群$, `既知な属性~群$ ]は、 ~HTML仕様から導出されるべきであり, ここには明示的に挙げられない。 現時点では,それを行う仕組みは無い。 ◎ 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.
`~navigate用の~URL属性~list@ は、 `javascript:@~HTMLnav#the-javascript:-url-special-case$l ~naviが安全でないものとされるものであり, 次の様な形で与えられる ( %HTMLNS は `~HTML名前空間$ ):
[ [ { `name^l → `a^l, `namespace^l → %HTMLNS }, { `name^l → `href^l, `namespace^l → ~NULL } ], [ { `name^l → `area^l, `namespace^l → %HTMLNS }, { `name^l → `href^l, `namespace^l → ~NULL } ], [ { `name^l → `form^l, `namespace^l → %HTMLNS }, { `name^l → `action^l, `namespace^l → ~NULL } ], [ { `name^l → `input^l, `namespace^l → %HTMLNS }, { `name^l → `formaction^l, `namespace^l → ~NULL } ], [ { `name^l → `button^l, `namespace^l → %HTMLNS }, { `name^l → `formaction^l, `namespace^l → ~NULL } ], ]◎ The navigating URL attributes list, for which "javascript:" navigations are unsafe, are as follows: ◎ «[ [ { "name" → "a", "namespace" → "HTML namespace" }, { "name" → "href", "namespace" → null } ], [ { "name" → "area", "namespace" → "HTML namespace" }, { "name" → "href", "namespace" → null } ], [ { "name" → "form", "namespace" → "HTML namespace" }, { "name" → "action", "namespace" → null } ], [ { "name" → "input", "namespace" → "HTML namespace" }, { "name" → "formaction", "namespace" → null } ], [ { "name" → "button", "namespace" → "HTML namespace" }, { "name" → "formaction", "namespace" → null } ], ]»
4. ~securityの考慮点
`無毒化器~API^i に意図されるのは、 ~DOMに基づく~XSS( `DOM-based Cross-Site Scripting^en )を防止することである — 給された~HTML内容を辿って,環境設定に則って[ 要素/属性 ]を除去することにより。 この~APIの仕様は、[ ~script能力がある~markupを残すような `Sanitizer^I ~objの構築 【!この `Sanitizer^I は、現在の `Sanitizer$I とは別物かも?】 ]を~supportしてはナラナイ — そうすることは、 脅威~modelにおける~bugになろう。 ◎ The Sanitizer API is intended to prevent DOM-based Cross-Site Scripting by traversing a supplied HTML content and removing elements and attributes according to a configuration. The specified API must not support the construction of a Sanitizer object that leaves script-capable markup in and doing so would be a bug in the threat model.
とは言え、 `無毒化器~API^i の正しい用法では保護-可能でない,~securityの課題はある — 以下の下位節では、 そのような局面について~~述べる。 ◎ That being said, there are security issues which the correct usage of the Sanitizer API will not be able to protect against and the scenarios will be laid out in the following sections.
4.1. ~server側に反映され, 格納される~XSS
◎非規範的`無毒化器~API^i は、 もっぱら~DOM内で演算する — それは、 既存の `DocumentFragment$I を辿って~filterするための能力を追加する。 `無毒化器~API^i は、[ ~server側に反映され, 格納される~XSS ]には取組まない。 ◎ The Sanitizer API operates solely in the DOM and adds a capability to traverse and filter an existing DocumentFragment. The Sanitizer does not address server-side reflected or stored XSS.
4.2. ~DOM~clobbering
◎非規範的~DOM~clobbering【 “痛めつけ” 】は、 悪意的な~HTMLで~appを惑わす攻撃である — そこでは、[ 要素の[ `id^a や `name^a ]属性を命名することにより,[ ~DOM内の~HTML要素の `children^m の様な~prop ]が悪意的な内容により隠蔽される。 ◎ DOM clobbering describes an attack in which malicious HTML confuses an application by naming elements through id or name attributes such that properties like children of an HTML element in the DOM are overshadowed by the malicious content.
`無毒化器~API^i は、 既定の状態では,~DOM~clobbering攻撃を保護しないが、 `id^a 属性や `name^a 属性を除去するよう環境設定することはできる。 ◎ The Sanitizer API does not protect DOM clobbering attacks in its default state, but can be configured to remove id and name attributes.
4.3. ~script~gadgetを伴う~XSS
◎非規範的~script~gadgetは、 既存の[ 普及している~JS~libraryからの~app~code ]を利用して,攻撃者が自前の~codeを実行させる技法である。 これは、[ ある~frameworkに限り,構文解析され解釈される ]ような[ 見かけは潔白な~code/不活そうに見える~DOM~node ]を注入することにより行われることが多く、 その入力に基づいて~JSの実行を遂行する。 ◎ Script gadgets are a technique in which an attacker uses existing application code from popular JavaScript libraries to cause their own code to execute. This is often done by injecting innocent-looking code or seemingly inert DOM nodes that is only parsed and interpreted by a framework which then performs the execution of JavaScript based on that input.
`無毒化器~API^i は、 これらの攻撃は防止できないが,[ 次に挙げるものは、 明示的に許容すること ]を~page作者に要求する: ◎ The Sanitizer API can not prevent these attacks, but requires page authors to explicitly allow\
- 未知な[ 属性/要素 ] — これらを許容するためには、 明示的に環境設定しなければナラナイ ◎ unknown elements in general, and authors must additionally explicitly configure unknown attributes and elements\
- [ ~template化, ~framework ]に特有な~code用に広く利用されていることが既知な~markup — [ `data-$a, `slot$a ]属性や[ `slot$e, `template$e ]要素など。 ◎ and markup that is known to be widely used for templating and framework-specific code, like data- and slot attributes and elements like <slot> and <template>.\
これらの制約は、 網羅的でないと予見される。 ~page作者には、[ 自身が利用している第三者-主体~libraryを,この挙動に関して精査すること ]が奨励される。 ◎ We believe that these restrictions are not exhaustive and encourage page authors to examine their third party libraries for this behavior.
4.4. ~mXSS
◎非規範的~mXSS ( `mutated Cross-Site Scripting^en / `mutated XSS^en の略称)は、[ ~HTML~code片を不正な文脈の下で構文解析するとき,構文解析器~文脈が合致しないこと ]に基づく攻撃である。 特に,【ある親~要素の中で】~HTML素片を構文解析してから文字列に直列化した結果は、 異なる親~要素の中に挿入されるとき,~~元と正確に同じに[ 構文解析され, 解釈される ]ことは保証されない。 そのような攻撃を遂げる例には、[ 外来な内容や誤って入子にされた~tagに対し,構文解析の挙動が変化すること ]に依拠するものがある。 ◎ Mutated XSS or mXSS describes an attack based on parser context mismatches when parsing an HTML snippet without the correct context. In particular, when a parsed HTML fragment has been serialized to a string, the string is not guaranteed to be parsed and interpreted exactly the same when inserted into a different parent element. An example for carrying out such an attack is by relying on the change of parsing behavior for foreign content or mis-nested tags.
`無毒化器~API^i は、 文字列を~node~treeへ転化する機能しか提供しない。 すべての無毒化器~関数は、 文脈を暗黙的に給する: `Element$I の `setHTML()$mE は現在の要素を利用し, `Document$I の `parseHTML()$m は新たな文書を作成する。 したがって、 `無毒化器~API^i は,~mXSSにより直に影響されることは無い。 ◎ The Sanitizer API offers only functions that turn a string into a node tree. The context is supplied implicitly by all sanitizer functions: Element.setHTML() uses the current element; Document.parseHTML() creates a new document. Therefore Sanitizer API is not directly affected by mutated XSS.
開発者が無毒化された~node~treeを — 例えば `innerHTML$mE を介して — 文字列として検索取得してから,その結果を再び構文解析した場合、 ~mXSSが生じ得る — なので,この実施は忌避される。 それでも,~HTMLを文字列として[ 処理する/渡す ]ことが必要yな場合、 文字列を~DOMの中へ挿入するときには, 信用-済みでないのと見なすベキであり,(再び)無毒化するベキである。 言い換えれば、 無毒化されてから直列化された~HTML~treeは, もはや無毒化-済みとは見なせない。 ◎ If a developer were to retrieve a sanitized node tree as a string, e.g. via .innerHTML, and to then parse it again then mutated XSS may occur. We discourage this practice. If processing or passing of HTML as a string should be necessary after all, then any string should be considered untrusted and should be sanitized (again) when inserting it into the DOM. In other words, a sanitized and then serialized HTML tree can no longer be considered as sanitized.
~mXSSに対する,より完全な扱いは、 `MXSS$r にて見出せる。 ◎ A more complete treatment of mXSS can be found in [MXSS].
5. 謝辞
`Cure53^en の `DOMPURIFY$r による[ この文書が述べる~API ]用の明瞭な発想に。 `Internet Explorer^en の `window.toStaticHTML()@https://msdn.microsoft.com/en-us/library/cc848922(v=vs.85).aspx$c にも。 ◎ Cure53’s [DOMPURIFY] is a clear inspiration for the API this document describes, as is Internet Explorer’s window.toStaticHTML().