コンテンツセキュリティポリシー

CSP とは?

コンテンツセキュリティポリシー (CSP) は、クロスサイトスクリプティング (XSS) やデータインジェクション攻撃などの特定の種類の攻撃を検出して軽減する追加のセキュリティレイヤーです。これらの攻撃は、データ窃盗からサイト改ざん、マルウェアの配布まで、あらゆる目的で使用されます。

統合手順

ルートプラグインの追加

ミドルウェアプラグインをアプリケーションに追加するには、[メールアドレスはスパム対策のため削除しました]という名前のファイルをroutesフォルダに追加します。このファイルはすべてのリクエストでロードされるため、ヘッダーの追加、レスポンスの変更などが可能です。

プラグインの追加
src/
└── routes/
    ├── [email protected]         # The plugin which runs on every request (route middleware)
    ├── contact/
       └── index.mdx         # https://example.com/contact
    ├── about/
       └── index.md          # https://example.com/about
    ├── index.mdx             # https://example.com/
    
    └── layout.tsx            # This layout is used for all pages

このテンプレートは、非常に寛容な下位互換性のあるデフォルト値を提供します。具体的なユースケースに合わせてカスタマイズすることを強くお勧めします。これは上級トピックであるため、CSP についてより深く理解するには、MDNまたはweb.devをよく確認してください。開発モードでは、Vite スクリプトには nonce がなく、報告されます。このため、この例では開発モードでは CSP を追加しません。

import type { RequestHandler } from "@builder.io/qwik-city";
import { isDev } from "@builder.io/qwik/build";
 
export const onRequest: RequestHandler = event => {
  if (isDev) return; // Will not return CSP headers in dev mode
  const nonce = Date.now().toString(36); // Your custom nonce logic here
  event.sharedMap.set("@nonce", nonce);
  const csp = [
    `default-src 'self' 'unsafe-inline'`,
    `font-src 'self'`,
    `img-src 'self' 'unsafe-inline' data:`,
    `script-src 'self' 'unsafe-inline' https: 'nonce-${nonce}' 'strict-dynamic'`,
    `style-src 'self' 'unsafe-inline'`,
    `frame-src 'self' 'nonce-${nonce}'`,
    `object-src 'none'`,
    `base-uri 'self'`,
  ];
 
  event.headers.set("Content-Security-Policy", csp.join("; "));
};

サービスワーカーにも追加する

src/root.ts
import { component$, useServerData } from "@builder.io/qwik";
import {
  QwikCityProvider,
  RouterOutlet,
  ServiceWorkerRegister,
} from "@builder.io/qwik-city";
import { RouterHead } from "./components/router-head/router-head";
import { isDev } from "@builder.io/qwik/build";
 
import "./global.css";
 
export default component$(() => {
  const nonce = useServerData<string | undefined>("nonce");
  return (
    <QwikCityProvider>
      <head>
        <meta charSet="utf-8" />
        {!isDev && <link rel="manifest" href={`${import.meta.env.BASE_URL}manifest.json`} />}
 
        <RouterHead />
      </head>
      <body lang="en">
        <RouterOutlet />
        {!isDev && <ServiceWorkerRegister nonce={nonce} />}
      </body>
    </QwikCityProvider>
  );
});

カスタムスクリプト

nonce を追加する必要があるカスタムスクリプトタグがある場合は、useServerDataフックを使用してサーバーから nonce を取得し、スクリプトタグに追加できます。

src/components/some-component.tsx
export default component$(() => {
  const nonce = useServerData<string | undefined>("nonce");
  return (
    <div>
      <script nonce={nonce}>alert("Hello world")</script>
    </div>
  );
});

CSP の検証

CSP を検証するための優れたツールがあります:https://csp-evaluator.withgoogle.com/

貢献者

このドキュメントの改善に貢献してくれたすべての貢献者への感謝を述べます!

  • tzdesign
  • jordanw66
  • mrhoodz
  • the-zimmermann
  • hamatoyogi