Nuxt.jsでサニタイズすることがあったので、sanitize-htmlの設定方法をメモ。
sanitize-html はバージョン 2.7.0 を使用しています。
設定方法
Nuxt.jsの環境にパッケージをインストールします。
yarn add sanitize-html
npmの場合は下記になります。
npm install sanitize-html
pluginsディレクトリにsanitize-html.jsを作成します。
import Vue from 'vue'; import sanitizeHTML from 'sanitize-html'; Vue.prototype.$sanitize = sanitizeHTML;
nuxt.config.jsのpluginsに先ほどのファイルパスを追加します。
export default { plugins: [ '@/plugins/sanitize-html' ] }
これで一通りの設定が完了したので、実際に試してみます。
<template> <div> <h2>サニタイズなし</h2> <div v-html="test"></div> <h2>サニタイズあり</h2> <div v-html="$sanitize(test)"></div> </div> </template> <script> export default { data(){ return{ test:` <p class="script" style="color: red;"><a onclick=alert("aaa")>alert</a></p> <p><img src="https://cly7796.net/blog/wp-content/uploads/2020/10/nuxtjs.jpg"></p> <iframe width="560" height="315" src="https://www.youtube.com/embed/6LXbazi_RHo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ` } }, } </script>
結果は以下のようになり、サニタイズありの方はimgやiframeといったタグやonclick、class、styleなどの属性が除去されました。
<h2>サニタイズなし</h2> <div> <p class="script" style="color: red;"><a onclick="alert("aaa")">alert</a></p> <p><img src="https://cly7796.net/blog/wp-content/uploads/2020/10/nuxtjs.jpg"></p> <iframe width="560" height="315" src="https://www.youtube.com/embed/6LXbazi_RHo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe> </div> <h2>サニタイズあり</h2> <div> <p><a>alert</a></p> <p></p> </div>
sanitize-htmlのドキュメントに記載がありますが、初期設定は以下のようになっているようです。
allowedTagsが許容するタグ、allowedAttributesがタグ毎に許容する属性になります。
allowedTags: [ "address", "article", "aside", "footer", "header", "h1", "h2", "h3", "h4", "h5", "h6", "hgroup", "main", "nav", "section", "blockquote", "dd", "div", "dl", "dt", "figcaption", "figure", "hr", "li", "main", "ol", "p", "pre", "ul", "a", "abbr", "b", "bdi", "bdo", "br", "cite", "code", "data", "dfn", "em", "i", "kbd", "mark", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp", "small", "span", "strong", "sub", "sup", "time", "u", "var", "wbr", "caption", "col", "colgroup", "table", "tbody", "td", "tfoot", "th", "thead", "tr" ], disallowedTagsMode: 'discard', allowedAttributes: { a: [ 'href', 'name', 'target' ], img: [ 'src', 'srcset', 'alt', 'title', 'width', 'height', 'loading' ] }, selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ], allowedSchemes: [ 'http', 'https', 'ftp', 'mailto', 'tel' ], allowedSchemesByTag: {}, allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ], allowProtocolRelative: true, enforceHtmlBoundary: false
先ほどの例でimgとiframeタグを許容したい場合、sanitize-html.jsに設定を追加します。
import Vue from 'vue'; import sanitizeHtml from 'sanitize-html'; sanitizeHtml.defaults.allowedTags = sanitizeHtml.defaults.allowedTags.concat(['img', 'iframe']); Vue.prototype.$sanitize = sanitizeHtml;
sanitizeHtml.defaults.allowedTags でデフォルトで許容されているタグの取得や設定ができます。
結果は以下のようにimgとiframeが許容されましたが、デフォルトではiframeの属性が許容されていないので、何も表示されません。
<h2>サニタイズなし</h2> <div> <p class="script" style="color: red;"><a onclick="alert("aaa")">alert</a></p> <p><img src="https://cly7796.net/blog/wp-content/uploads/2020/10/nuxtjs.jpg"></p> <iframe width="560" height="315" src="https://www.youtube.com/embed/6LXbazi_RHo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe> </div> <h2>サニタイズあり</h2> <div> <p><a>alert</a></p> <p><img src="https://cly7796.net/blog/wp-content/uploads/2020/10/nuxtjs.jpg"></p> <iframe></iframe> </div>
iframeの各属性と、全ての要素のclass属性とstyle属性の許容を試してみます。
先ほどと同様、sanitize-html.jsに設定を追加します。
import Vue from 'vue'; import sanitizeHtml from 'sanitize-html'; sanitizeHtml.defaults.allowedTags = sanitizeHtml.defaults.allowedTags.concat(['img', 'iframe']); sanitizeHtml.defaults.allowedAttributes['iframe'] = ['*']; sanitizeHtml.defaults.allowedAttributes['*'] = ['class', 'style']; Vue.prototype.$sanitize = sanitizeHtml;
これでiframeの各属性とclass属性、style属性の許容ができました。
<h2>サニタイズなし</h2> <div> <p class="script" style="color: red;"><a onclick="alert("aaa")">alert</a></p> <p><img src="https://cly7796.net/blog/wp-content/uploads/2020/10/nuxtjs.jpg"></p> <iframe width="560" height="315" src="https://www.youtube.com/embed/6LXbazi_RHo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe> </div> <h2>サニタイズあり</h2> <div> <p class="script" style="color:red"><a>alert</a></p> <p><img src="https://cly7796.net/blog/wp-content/uploads/2020/10/nuxtjs.jpg"></p> <iframe width="560" height="315" src="https://www.youtube.com/embed/6LXbazi_RHo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe> </div>
他にも色々な設定が行えるので、詳しくはsanitize-htmlのページをご確認ください。
コメントが承認されるまで時間がかかります。