diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index b473fad3..5a60cc52 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -106,7 +106,7 @@ const sidebar = { { title: 'スケールアップ', collapsable: false, - children: ['/guide/routing', '/guide/state-management', '/guide/ssr'] + children: ['/guide/routing', '/guide/state-management', '/guide/ssr', '/guide/security'] }, { title: 'アクセシビリティ', diff --git a/src/guide/security.md b/src/guide/security.md new file mode 100644 index 00000000..e688f0ee --- /dev/null +++ b/src/guide/security.md @@ -0,0 +1,187 @@ +# セキュリティ + +## 脆弱性の報告 + +脆弱性が報告されると、それは直ちに私たちの最重要課題となり、フルタイムコミットのコントリビュータがすべてを投げ出して取り組みます。脆弱性の報告は、[security@vuejs.org](mailto:security@vuejs.org) までメールしてください。 + +新しい脆弱性が発見されることはめったにありませんが、あなたのアプリケーションを可能な限り安全に保つために、Vue とその公式ライブラリの最新バージョンを常に利用することをおすすめします。 + +## 一番のルール: 信頼できないテンプレートを使わない + +Vue を使うときの最も基本的なセキュリティルールは、 **信頼されていないコンテンツをコンポーネントのテンプレートに使わないこと** です。これはあなたのアプリケーションで任意の JavaScript の実行を許可することと同じで、さらに悪いことに、そのコードがサーバサイドレンダリング中に実行されると、サーバの侵害につながる可能性があります。そのような使い方の例です: + +```js +Vue.createApp({ + template: `
` + userProvidedString + `
` // 絶対にやってはいけないこと +}).mount('#app') +``` + +Vue のテンプレートは JavaScript にコンパイルされていて、テンプレート内の式はレンダリング処理の一部として実行されます。それらの式は特定のレンダリング・コンテキストに対して評価されますが、潜在的にグローバル実行環境が複雑なため、Vue のようなフレームワークが非現実的なパフォーマンスのオーバーヘッドを発生させることなく、潜在的な悪意のあるコードの実行から完全に保護することは現実的ではありません。このカテゴリの問題を完全に回避する最も簡単な方法は、あなたの Vue テンプレートのコンテンツが常に信頼され、完全に制御されるようにすることです。 + +## Vue があなたを守るために行っていること + +### HTML コンテンツ + +テンプレートでも Render 関数でも、コンテンツは自動的にエスケープされます。つまり、このテンプレートでは: + +```html +

{{ userProvidedString }}

+``` + +`userProvidedString` が含まれている場合: + +```js +'' +``` + +これは次のような HTML にエスケープされます: + +```html +<script>alert("hi")</script> +``` + +これにより、スクリプトの注入を防ぐことができます。このエスケープは、`textContent` のようなブラウザのネイティブ API を使って行われるため、ブラウザ自体に脆弱性がある場合にのみ脆弱性が存在します。 + +### 属性の束縛 + +同じように、動的な属性の束縛も自動的にエスケープされます。つまり、このテンプレートでは: + +```html +

+ hello +

+``` + +`userProvidedString` が含まれている場合: + +```js +'" onclick="alert(\'hi\')' +``` + +これは次のような HTML にエスケープされます: + +```html +" onclick="alert('hi') +``` + +これにより、新しい任意の HTML を注入するために `title` 属性を閉じることができなくなります。このエスケープは、`setAttribute` のようなブラウザのネイティブ API を使って行われるため、ブラウザ自体に脆弱性がある場合にのみ脆弱性が存在します。 + +## 潜在的な危険性 + +ウェブアプリケーションにおいてはどれも、ユーザが提供したサニタイズしていないコンテンツを HTML、CSS、JavaScript として実行させることは、潜在的に危険なため、可能な限り避けるべきです。しかし、いくつかのリスクを許容できる場合もあるでしょう。 + +例えば、CodePen や JSFiddle といったサービスでは、ユーザが提供したコンテンツを実行することができますが、それは iframe の中である程度サンドボックス化されていて、想定されたコンテキストの中でのことです。もし重要な機能が本質的にいくらかの脆弱性を必要とする場合、その機能の重要性とその脆弱性が起こす可能性のある最悪のシナリオを比較検討するのは、あなたのチームの責任です。 + +### HTML の注入 + +以前学んだように、Vue は自動的に HTML コンテンツをエスケープして、あなたのアプリケーション内で実行可能な HTML を誤って注入してしまうことを防ぎます。しかし、HTML が安全だとわかっている場合には、HTML コンテンツを明示的にレンダリングすることができます: + +- テンプレートを利用: + + ```html +
+ ``` + +- Render 関数を利用: + + ```js + h('div', { + innerHTML: this.userProvidedHtml + }) + ``` + +- JSX と Render 関数を利用: + + ```jsx +
+ ``` + +:::tip +ユーザが提供した HTML は、サンドボックス化された iframe や、その HTML を書いたユーザだけがアクセスできるアプリケーションの一部に置かない限り、100% 安全とは言えないことに注意してください。加えて、ユーザが独自の Vue テンプレートを書けるようにしても同様の危険があります。 +::: + +### URL の注入 + +このような URL で: + +```html + + click me + +``` + +`javascript:` を使った JavaScript の実行を防ぐ URL の「サニタイズ」がされていないと、これにはセキュリティの問題を抱える可能性があります。[sanitize-url](https://www.npmjs.com/package/@braintree/sanitize-url) のようなライブラリがこのような問題の助けになりますが、注意が必要です: + +:::tip +あなたがフロントエンドで URL のサニタイズをしているのであれば、すでにセキュリティの問題があります。ユーザが提供した URL は、データベースに保存する前に、常にバックエンドでサニタイズされるべきです。そうすれば、ネイティブ・モバイルアプリケーションを含む API に接続する _すべての_ クライアントに対して、この問題を回避することができます。またサニタイズされた URL でも、Vue はそれが安全なリンク先につながることを保証できないことに注意してください。 +::: + +### スタイルの注入 + +この例を見てください: + +```html + + click me + +``` + +`sanitizedUrl` がサニタイズされていて、JavaScript ではない本物の URL だということが明確だとします。`userProvidedStyles` を利用して、悪意のあるユーザは「クリックジャック」のための CSS をまだ与えることができます。例えば、リンクを「ログイン」ボタンの上に透明なボックスで追加スタイルできます。それから `https://user-controlled-website.com/` があなたのアプリケーションのログインページに似せて作られていた場合、悪意のあるユーザはユーザの本当のログイン情報を取得してしまうかもしれません。 + +` +``` + +クリックジャックからユーザを完全に守るために、サンドボックス化された iframe 内でのみ CSS の完全な制御を許可することをおすすめします。 あるいは、スタイル・バインディングでユーザの制御をするなら、[オブジェクト構文](class-and-style.html#object-syntax-2) を使って、このようにユーザが制御しても安全な特定のプロパティにのみ値を提供することをおすすめします: + +```html + + click me + +``` + +### JavaScript の注入 + +テンプレートや Render 関数には副作用があってはならないため、Vue で `