From bc529fb92ec04f2856fa5b605a5a87fab0c17634 Mon Sep 17 00:00:00 2001 From: Naoki Endoh Date: Fri, 25 Jun 2021 00:44:32 +0900 Subject: [PATCH 1/3] Migrate security guide from Vue 2 https://github.com/vuejs/docs/commit/72d969a9463d493c8af55bcb9485c4fdf0fbb59c --- src/.vuepress/config.js | 2 +- src/guide/security.md | 187 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 src/guide/security.md 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..5f7813e0 --- /dev/null +++ b/src/guide/security.md @@ -0,0 +1,187 @@ +# Security + +## Reporting Vulnerabilities + +When a vulnerability is reported, it immediately becomes our top concern, with a full-time contributor dropping everything to work on it. To report a vulnerability, please email [security@vuejs.org](mailto:security@vuejs.org). + +While the discovery of new vulnerabilities is rare, we also recommend always using the latest versions of Vue and its official companion libraries to ensure your application remains as secure as possible. + +## Rule No.1: Never Use Non-trusted Templates + +The most fundamental security rule when using Vue is **never use non-trusted content as your component template**. Doing so is equivalent to allowing arbitrary JavaScript execution in your application - and worse, could lead to server breaches if the code is executed during server-side rendering. An example of such usage: + +```js +Vue.createApp({ + template: `
` + userProvidedString + `
` // NEVER DO THIS +}).mount('#app') +``` + +Vue templates are compiled into JavaScript, and expressions inside templates will be executed as part of the rendering process. Although the expressions are evaluated against a specific rendering context, due to the complexity of potential global execution environments, it is impractical for a framework like Vue to completely shield you from potential malicious code execution without incurring unrealistic performance overhead. The most straightforward way to avoid this category of problems altogether is to make sure the contents of your Vue templates are always trusted and entirely controlled by you. + +## What Vue Does to Protect You + +### HTML content + +Whether using templates or render functions, content is automatically escaped. That means in this template: + +```html +

{{ userProvidedString }}

+``` + +if `userProvidedString` contained: + +```js +'' +``` + +then it would be escaped to the following HTML: + +```html +<script>alert("hi")</script> +``` + +thus preventing the script injection. This escaping is done using native browser APIs, like `textContent`, so a vulnerability can only exist if the browser itself is vulnerable. + +### Attribute bindings + +Similarly, dynamic attribute bindings are also automatically escaped. That means in this template: + +```html +

+ hello +

+``` + +if `userProvidedString` contained: + +```js +'" onclick="alert(\'hi\')' +``` + +then it would be escaped to the following HTML: + +```html +" onclick="alert('hi') +``` + +thus preventing the close of the `title` attribute to inject new, arbitrary HTML. This escaping is done using native browser APIs, like `setAttribute`, so a vulnerability can only exist if the browser itself is vulnerable. + +## Potential Dangers + +In any web application, allowing unsanitized, user-provided content to be executed as HTML, CSS, or JavaScript is potentially dangerous, so should be avoided wherever possible. There are times when some risk may be acceptable though. + +For example, services like CodePen and JSFiddle allow user-provided content to be executed, but it's in a context where this is expected and sandboxed to some extent inside iframes. In the cases when an important feature inherently requires some level of vulnerability, it's up to your team to weigh the importance of the feature against the worst-case scenarios the vulnerability enables. + +### Injecting HTML + +As you learned earlier, Vue automatically escapes HTML content, preventing you from accidentally injecting executable HTML into your application. However, in cases where you know the HTML is safe, you can explicitly render HTML content: + +- Using a template: + + ```html +
+ ``` + +- Using a render function: + + ```js + h('div', { + innerHTML: this.userProvidedHtml + }) + ``` + +- Using a render function with JSX: + + ```jsx +
+ ``` + +:::tip +Note that user-provided HTML can never be considered 100% safe unless it's in a sandboxed iframe or in a part of the app where only the user who wrote that HTML can ever be exposed to it. Additionally, allowing users to write their own Vue templates brings similar dangers. +::: + +### Injecting URLs + +In a URL like this: + +```html + + click me + +``` + +There's a potential security issue if the URL has not been "sanitized" to prevent JavaScript execution using `javascript:`. There are libraries such as [sanitize-url](https://www.npmjs.com/package/@braintree/sanitize-url) to help with this, but note: + +:::tip +If you're ever doing URL sanitization on the frontend, you already have a security issue. User-provided URLs should always be sanitized by your backend before even being saved to a database. Then the problem is avoided for _every_ client connecting to your API, including native mobile apps. Also note that even with sanitized URLs, Vue cannot help you guarantee that they lead to safe destinations. +::: + +### Injecting Styles + +Looking at this example: + +```html + + click me + +``` + +let's assume that `sanitizedUrl` has been sanitized, so that it's definitely a real URL and not JavaScript. With the `userProvidedStyles`, malicious users could still provide CSS to "click jack", e.g. styling the link into a transparent box over the "Log in" button. Then if `https://user-controlled-website.com/` is built to resemble the login page of your application, they might have just captured a user's real login information. + +You may be able to imagine how allowing user-provided content for a ` +``` + +To keep your users fully safe from click jacking, we recommend only allowing full control over CSS inside a sandboxed iframe. Alternatively, when providing user control through a style binding, we recommend using its [object syntax](class-and-style.html#object-syntax-2) and only allowing users to provide values for specific properties it's safe for them to control, like this: + +```html + + click me + +``` + +### Injecting JavaScript + +We strongly discourage ever rendering a `' ``` -then it would be escaped to the following HTML: +これは次のような HTML にエスケープされます: ```html <script>alert("hi")</script> ``` -thus preventing the script injection. This escaping is done using native browser APIs, like `textContent`, so a vulnerability can only exist if the browser itself is vulnerable. +これにより、スクリプトの注入を防ぐことができます。このエスケープは、`textContent` のようなブラウザのネイティブ API を使って行われるため、ブラウザ自体に脆弱性がある場合にのみ脆弱性が存在します。 -### Attribute bindings +### 属性の束縛 -Similarly, dynamic attribute bindings are also automatically escaped. That means in this template: +同じように、動的な属性の束縛も自動的にエスケープされます。つまり、このテンプレートでは: ```html

@@ -52,37 +52,37 @@ Similarly, dynamic attribute bindings are also automatically escaped. That means

``` -if `userProvidedString` contained: +`userProvidedString` が含まれている場合: ```js '" onclick="alert(\'hi\')' ``` -then it would be escaped to the following HTML: +これは次のような HTML にエスケープされます: ```html " onclick="alert('hi') ``` -thus preventing the close of the `title` attribute to inject new, arbitrary HTML. This escaping is done using native browser APIs, like `setAttribute`, so a vulnerability can only exist if the browser itself is vulnerable. +これにより、新しい任意の HTML を注入するために `title` 属性を閉じることができなくなります。このエスケープは、`setAttribute` のようなブラウザのネイティブ API を使って行われるため、ブラウザ自体に脆弱性がある場合にのみ脆弱性が存在します。 -## Potential Dangers +## 潜在的な危険性 -In any web application, allowing unsanitized, user-provided content to be executed as HTML, CSS, or JavaScript is potentially dangerous, so should be avoided wherever possible. There are times when some risk may be acceptable though. +ウェブアプリケーションにおいてはどれも、ユーザが提供したサニタイズしていないコンテンツを HTML、CSS、JavaScript として実行させることは、潜在的に危険なため、可能な限り避けるべきです。しかし、いくつかのリスクを許容できる場合もあるでしょう。 -For example, services like CodePen and JSFiddle allow user-provided content to be executed, but it's in a context where this is expected and sandboxed to some extent inside iframes. In the cases when an important feature inherently requires some level of vulnerability, it's up to your team to weigh the importance of the feature against the worst-case scenarios the vulnerability enables. +例えば、CodePen や JSFiddle といったサービスでは、ユーザが提供したコンテンツを実行することができますが、それは iframe の中である程度サンドボックス化されていて、想定されたコンテキストの中でのことです。もし重要な機能が本質的にいくらかの脆弱性を必要とする場合、その機能の重要性とその脆弱性が起こす可能性のある最悪のシナリオを比較検討するのは、あなたのチームの責任です。 -### Injecting HTML +### HTML の注入 -As you learned earlier, Vue automatically escapes HTML content, preventing you from accidentally injecting executable HTML into your application. However, in cases where you know the HTML is safe, you can explicitly render HTML content: +以前学んだように、Vue は自動的に HTML コンテンツをエスケープして、あなたのアプリケーション内で実行可能な HTML を誤って注入してしまうことを防ぎます。しかし、HTML が安全だとわかっている場合には、HTML コンテンツを明示的にレンダリングすることができます: -- Using a template: +- テンプレートを利用: ```html
``` -- Using a render function: +- Render 関数を利用: ```js h('div', { @@ -90,19 +90,19 @@ As you learned earlier, Vue automatically escapes HTML content, preventing you f }) ``` -- Using a render function with JSX: +- JSX と Render 関数を利用: ```jsx
``` :::tip -Note that user-provided HTML can never be considered 100% safe unless it's in a sandboxed iframe or in a part of the app where only the user who wrote that HTML can ever be exposed to it. Additionally, allowing users to write their own Vue templates brings similar dangers. +ユーザが提供した HTML は、サンドボックス化された iframe や、その HTML を書いたユーザだけがアクセスできるアプリケーションの一部に置かない限り、100% 安全とは言えないことにちゅうしてください。加えて、ユーザが独自の Vue テンプレートを書けるようにしても同様の危険があります。 ::: -### Injecting URLs +### URL の注入 -In a URL like this: +このような URL で: ```html @@ -110,13 +110,13 @@ In a URL like this: ``` -There's a potential security issue if the URL has not been "sanitized" to prevent JavaScript execution using `javascript:`. There are libraries such as [sanitize-url](https://www.npmjs.com/package/@braintree/sanitize-url) to help with this, but note: +`javascript:` を使った JavaScript の実行を防ぐ URL の「サニタイズ」がされていないと、これにはセキュリティの問題を抱える可能性があります。[sanitize-url](https://www.npmjs.com/package/@braintree/sanitize-url) のようなライブラリがこのような問題の助けになりますが、注意が必要です: :::tip -If you're ever doing URL sanitization on the frontend, you already have a security issue. User-provided URLs should always be sanitized by your backend before even being saved to a database. Then the problem is avoided for _every_ client connecting to your API, including native mobile apps. Also note that even with sanitized URLs, Vue cannot help you guarantee that they lead to safe destinations. +あなたがフロントエンドで URL のサニタイズをしているのであれば、すでにセキュリティの問題があります。ユーザが提供した URL は、データベースに保存する前に、常にバックエンドでサニタイズされるべきです。そうすれば、ネイティブ・モバイルアプリケーションを含む API に接続する _すべての_ クライアントに対して、この問題を回避することができます。またサニタイズされた URL でも、Vue はそれが安全なリンク先につながることを保証できないことに注意してください。 ::: -### Injecting Styles +### スタイルの注入 Looking at this example: @@ -151,7 +151,7 @@ To keep your users fully safe from click jacking, we recommend only allowing ful ``` -### Injecting JavaScript +### JavaScript の注入 We strongly discourage ever rendering a `