Content Security Policy Level 3 を使う方法
nonce とハッシュを用いた厳格な Content Security Policy(CSP3)を設定し、XSS、データ流出、コードインジェクション攻撃を防ぎます。
问题
インラインスクリプトや外部リソースを攻撃者に注入される可能性があり、Web アプリケーションがクロスサイトスクリプティング(XSS)に対して脆弱です。信頼できるソースのみを許可する厳格な Content Security Policy(CSP Level 3)を実装する必要があります。
前提条件
- XSS 攻撃とインジェクション経路の理解
- HTTP ヘッダーとブラウザのセキュリティポリシーへの習熟
- スクリプトの nonce とサブリソースインテグリティに関する知識
ステップ
-
1. Start with a restrictive default policy
Begin with the most restrictive policy: default-src 'none'. This blocks everything by default. Then explicitly allow only what each resource type needs. This deny-by-default approach is more secure than allow-by-default. Use the HTML sanitizer to understand what content needs to be allowed. Start with: Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; base-uri 'none'; form-action 'self'
入力default-src 'none'; script-src 'self'; style-src 'self'输出all external and inline resources blocked except same-origin scripts and styles -
2. Use nonces or hashes for inline scripts
CSP3 supports nonces (number used once) for inline scripts. Generate a unique random nonce per request, add it to the CSP header (script-src 'self' 'nonce-<random>'), and add the same nonce attribute to each inline script tag: <script nonce='<random>'. This is more secure than 'unsafe-inline'. Alternatively, use hashes: compute SHA256 of the inline script content and add 'sha256-<hash>' to script-src. Use the hash and base64 tools to compute script hashes.
入力inline script: console.log('hello')输出nonce: rAnd0mN0nc3 | CSP: script-src 'self' 'nonce-rAnd0mN0nc3' -
3. Add strict-dynamic and reporting
CSP3 'strict-dynamic' allows scripts loaded by trusted (nonced or hashed) scripts to also execute, simplifying third-party library support. Add a reporting directive: report-uri /csp-report or report-to endpoint. The browser sends violation reports to this endpoint without blocking, useful for monitoring before enforcing. Use Report-Only mode first (Content-Security-Policy-Report-Only) to identify violations without breaking the page.
入力script-src 'nonce-rAnd0mN0nc3' 'strict-dynamic'输出trusted scripts can load dependencies | violations reported to /csp-report -
4. Enforce and test the policy
Switch from Report-Only to enforcing mode once all violations are resolved. Test with XSS payloads to confirm they are blocked. Add frame-ancestors 'none' to prevent clickjacking (equivalent to X-Frame-Options: DENY). Add upgrade-insecure-requests to force HTTPS. Add require-trusted-types-for 'script' (CSP3 Trusted Types) to prevent DOM XSS via dangerous sinks. Use the HTML escape tool to verify proper output encoding complements CSP.
入力XSS payload: <script>alert(1)</script>输出blocked by CSP | report: violated script-src 'nonce-...' directive
期待される結果
XSS、クリックジャッキング、ミックスコンテンツ、データ流出を防ぐ、違反監視付きの厳格な CSP レベル 3 ポリシー。
よくあるエラー
- Using 'unsafe-inline' for scripts
- 'unsafe-inline' defeats CSP's XSS protection. Use nonces or hashes (CSP3) instead. If using nonces, 'unsafe-inline' is ignored by browsers anyway.
- Using 'unsafe-eval' for dynamic code
- 'unsafe-eval' allows eval() and new Function(), reintroducing XSS risk. Refactor to avoid dynamic evaluation, or use CSP3 'strict-dynamic' with trusted scripts.
- Deploying CSP in enforce mode without testing
- Start with Content-Security-Policy-Report-Only, collect violation reports, fix all violations, then switch to enforcing mode. Enforcing immediately can break the application.
トラブルシューティング指引
- If third-party scripts are blocked, either add their domains to script-src or use 'strict-dynamic' with a nonced loader script that loads them.
- If inline styles break, use nonces for style-src as well, or move styles to external stylesheets.
- For single-page applications, ensure the CSP applies to all routes and that dynamic imports are covered by the script-src policy.
セキュリティ上の制限
- CSP is defense-in-depth — it does not replace proper output encoding and input validation. Both are needed.
- CSP does not protect against CSS-based data exfiltration in all cases — use 'style-src' restrictions carefully.
- All policy generation and nonce generation happen server-side; the browser enforces the policy locally.