Sanitizer API を使ってみる

1. このページの目的

Sanitizer API を使ってみる。

2. Sanitizer API の機能

3. デモ

Safe DOM manipulation with the Sanitizer API に載っているコード

サニタイズ結果の文字列はコンソール上にも出力しているので、Chrome DevTools で確認できる。

3-1. 危険な箇所(ここではHTMLタグの属性)は削除される

Safe DOM manipulation with the Sanitizer API

JavaScript

const $span3_1 = document.querySelector('#output3-1');
const user_input3_1 = `<em>hello world</em><img src="" onerror=alert(0)>`
$span1.setHTML(user_input3_1, { sanitizer: new Sanitizer() });

結果

3-2. <script>タグを渡すとどうなるか?

個人的に試したかったもの。

JavaScript

const $span3_2 = document.querySelector('#output3-2');
const user_input3_2 = '<script>alert(1)<\/script>';
$span3_2.setHTML(user_input3_2, { sanitizer: new Sanitizer() });

結果

3-2a. onerrorを渡すとどうなるか?

個人的に試したかったもの。

JavaScript

const $span3_2a = document.querySelector('#output3-2a');
const user_input3_2a = '<img src=/ onerror=alert(1)>';
$span3_2a.setHTML(user_input3_2a, { sanitizer: new Sanitizer() });

結果

3-3. オプションを試す (allowElements, blockElements, dropElements)

Safe DOM manipulation with the Sanitizer API

JavaScript

const str3_3 = `hello <b><i>world</i></b>`
const $p3_3a = document.querySelector('#output3-3a');
const $p3_3b = document.querySelector('#output3-3b');
const $p3_3c = document.querySelector('#output3-3c');
const $p3_3d = document.querySelector('#output3-3d');

$p3_3a.setHTML(str3_3)
// <p>hello <b><i>world</i></b></p>

$p3_3b.setHTML(str3_3, { sanitizer: new Sanitizer({allowElements: [ "b" ]}) })
// <p>hello <b>world</b></p>

$p3_3c.setHTML(str3_3, { sanitizer: new Sanitizer({blockElements: [ "b" ]}) })
// <p>hello <i>world</i></p>

$p3_3d.setHTML(str3_3, { sanitizer: new Sanitizer({allowElements: []}) })
// <p>hello world</p>

結果

3-4. オプションを試す (allowAttributes, dropAttributes)

Safe DOM manipulation with the Sanitizer API

JavaScript

const str3_4 = `<span id=foo class=bar style="color: red">hello</span>`
const $p3_4a = document.querySelector('#output3-4a');
const $p3_4b = document.querySelector('#output3-4b');
const $p3_4c = document.querySelector('#output3-4c');
const $p3_4d = document.querySelector('#output3-4d');
const $p3_4e = document.querySelector('#output3-4e');
const $p3_4f = document.querySelector('#output3-4f');

$p3_4a.setHTML(str3_4)
// <p><span id="foo" class="bar" style="color: red">hello</span></p>

$p3_4b.setHTML(str3_4, { sanitizer: new Sanitizer({allowAttributes: {"style": ["span"]}}) })
// <p><span style="color: red">hello</span></p>

$p3_4c.setHTML(str3_4, { sanitizer: new Sanitizer({allowAttributes: {"style": ["p"]}}) })
// <p><span>hello</span></p>

$p3_4d.setHTML(str3_4, { sanitizer: new Sanitizer({allowAttributes: {"style": ["*"]}}) })
// <p><span style="color: red">hello</span></p>

$p3_4e.setHTML(str3_4, { sanitizer: new Sanitizer({dropAttributes: {"id": ["span"]}}) })
// <p><span class="bar" style="color: red">hello</span></p>

$p3_4f.setHTML(str3_4, { sanitizer: new Sanitizer({allowAttributes: {}}) })
// <p>hello</p>

結果

3-5. オプションを試す (custom-elem)

Safe DOM manipulation with the Sanitizer API

JavaScript

customElements.define('custom-elem', class extends HTMLElement {
  constructor() {
    super();
    let shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = `Hello!`;
  }
});

const str3_5 = `<custom-elem>hello</custom-elem>`
const $p3_5a = document.querySelector('#output3-5a');
const $p3_5b = document.querySelector('#output3-5b');

$p3_5a.setHTML(str3_5)
// <p></p>

const sanitizer3_5 = new Sanitizer({
  allowCustomElements: true,
  allowElements: ["p", "custom-elem"]
})
$p3_5b.setHTML(str3_5, { sanitizer3_5 })
// <p><custom-elem>hello</custom-elem></p>

結果

3-6. DOMPurify の例

Safe DOM manipulation with the Sanitizer API

JavaScript

const $p3_6 = document.querySelector('#output3-6');
const user_input3_6 = `<em>hello world</em><img src="" onerror=alert(0)>`
const sanitized3_6 = DOMPurify.sanitize(user_input3_6)
$p3_6.innerHTML = sanitized3_6
// `<em>hello world</em><img src="">`

結果

4. デモ

HTML Sanitizer API に載っているコード

4-1. どの要素の中かによって、処理が異なる

1.3. The Trouble With Strings, EXAMPLE 2

JavaScript

const $div4_1a = document.querySelector('#output4-1a');
const user_input4_1a = `<em>bla`
$div4_1a.setHTML(user_input4_1a, { sanitizer: new Sanitizer() });

const $textarea4_1b = document.querySelector('#output4-1b');
const user_input4_1b = `<em>bla`
$textarea4_1b.setHTML(user_input4_1b, { sanitizer: new Sanitizer() });

結果

4-2. どの要素の中かによって、処理が異なる

1.3. The Trouble With Strings, EXAMPLE 3

JavaScript

const user_input4_2 = `<td>text`

const $table4_2a = document.querySelector('#output4-2a');
$table4_2a.setHTML(user_input4_2, { sanitizer: new Sanitizer() });

const $div4_2b = document.querySelector('#output4-2b');
$div4_2b.setHTML(user_input4_2, { sanitizer: new Sanitizer() });

結果

4-3. HTMLのコードを表示する

<pre><code> タグにHTMLコードを書いてみる。

JavaScript

const user_input4_3_1 = `<em>text</em>`
const $span4_3_1 = document.querySelector('#output4-3-1');
$span4_3_1.setHTML(user_input4_3_1, { sanitizer: new Sanitizer() });

const user_input4_3_2 = `&lt;em&gt;text&lt;/em&gt;`
const $span4_3_2 = document.querySelector('#output4-3-2');
$span4_3_2.setHTML(user_input4_3_2, { sanitizer: new Sanitizer() });

結果

5. メモ

6. 参考

※ 2022年9月現在で、Sanitizer API: sanitizeSanitizer API: sanitizeFor は未実装。