helmet の使い方

help secure Express/Connect apps with various HTTP headers

v8.1.0/週MITWeb API
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

helmet の使い方 — Express アプリのセキュリティヘッダーを一括設定

一言でいうと

helmet は、Express アプリケーションの HTTP レスポンスヘッダーを適切に設定し、XSS・クリックジャッキング・MIME スニッフィングなど、よくある Web 攻撃からアプリを保護するセキュリティミドルウェアです。app.use(helmet()) の一行で 13 種類以上のセキュリティヘッダーをまとめて設定できます。

どんな時に使う?

  1. Express で API サーバーや Web アプリを構築するとき — デフォルトの Express はセキュリティ関連のヘッダーをほとんど設定しないため、helmet を入れるだけで基本的な防御が整います
  2. Content-Security-Policy(CSP)を導入したいとき — CSP のディレクティブを柔軟に設定でき、nonce ベースのポリシーにも対応しています
  3. セキュリティ監査や脆弱性スキャンで指摘を受けたときX-Frame-OptionsStrict-Transport-SecurityX-Content-Type-Options など、よく指摘されるヘッダーを一括で対応できます

インストール

# npm
npm install helmet

# yarn
yarn add helmet

# pnpm
pnpm add helmet

以下の解説は helmet v8.x 系(2024年時点の最新メジャーバージョン)に基づいています。

基本的な使い方

最もシンプルなパターンは、Express ミドルウェアとして helmet() を呼ぶだけです。

import express from "express";
import helmet from "helmet";

const app = express();

// すべてのデフォルトヘッダーを一括設定
app.use(helmet());

app.get("/", (_req, res) => {
  res.send("Hello, secure world!");
});

app.listen(3000, () => {
  console.log("Server running on port 3000");
});

これだけで、以下のヘッダーが自動的にレスポンスに付与されます。

ヘッダーデフォルト値効果
Content-Security-Policydefault-src 'self'; ...XSS 等の攻撃を緩和
Cross-Origin-Opener-Policysame-originプロセス分離
Cross-Origin-Resource-Policysame-originクロスオリジンのリソース読み込みをブロック
Origin-Agent-Cluster?1オリジンベースのプロセス分離
Referrer-Policyno-referrerReferer ヘッダーの制御
Strict-Transport-Securitymax-age=15552000; includeSubDomainsHTTPS の強制
X-Content-Type-OptionsnosniffMIME スニッフィング防止
X-DNS-Prefetch-ControloffDNS プリフェッチの制御
X-Download-OptionsnoopenIE でのダウンロード自動実行防止
X-Frame-OptionsSAMEORIGINクリックジャッキング防止
X-Permitted-Cross-Domain-PoliciesnoneAdobe 製品のクロスドメイン制御
X-XSS-Protection0レガシー XSS フィルタを無効化(有効にすると逆に危険なため)

また、X-Powered-By ヘッダーは削除されます。

よく使う API — helmet の使い方詳細

1. Content-Security-Policy のカスタマイズ

最も設定頻度が高いヘッダーです。directives オブジェクトで各ディレクティブを上書きできます。

import helmet from "helmet";

app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'", "https://cdn.example.com"],
        styleSrc: ["'self'", "https://fonts.googleapis.com", "'unsafe-inline'"],
        imgSrc: ["'self'", "data:", "https://images.example.com"],
        fontSrc: ["'self'", "https://fonts.gstatic.com"],
        connectSrc: ["'self'", "https://api.example.com"],
        // null を指定するとデフォルトのディレクティブを削除
        "style-src": null,
      },
    },
  })
);

ディレクティブ名はキャメルケース(scriptSrc)でもケバブケース("script-src")でも指定できます。

2. CSP で nonce を使う

SPA やインラインスクリプトを安全に許可するための nonce パターンです。

import crypto from "crypto";
import helmet from "helmet";

// リクエストごとに nonce を生成
app.use((_req, res, next) => {
  res.locals.cspNonce = crypto.randomBytes(32).toString("hex");
  next();
});

app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        scriptSrc: [
          "'self'",
          (_req, res) => `'nonce-${(res as any).locals.cspNonce}'`,
        ],
      },
    },
  })
);

app.get("/", (_req, res) => {
  res.send(`
    <html>
      <body>
        <script nonce="${res.locals.cspNonce}">
          console.log("This script is allowed");
        </script>
      </body>
    </html>
  `);
});

3. 特定のヘッダーを無効化する

不要なヘッダーや、アプリの要件と競合するヘッダーは false で無効化できます。

app.use(
  helmet({
    // CSP は別のミドルウェアで管理する場合など
    contentSecurityPolicy: false,
    // iframe での埋め込みを許可したい場合
    xFrameOptions: false,
  })
);

4. 個別のミドルウェアとして使う

helmet の各機能は、スタンドアロンのミドルウェアとしても利用できます。特定のルートにだけ適用したい場合に便利です。

import helmet from "helmet";

// 全体には基本設定を適用
app.use(helmet());

// 特定のルートだけ CSP を上書き
app.get(
  "/widget",
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "https://widget.example.com"],
      frameAncestors: ["https://partner-site.com"],
    },
  }),
  (_req, res) => {
    res.send("Widget page with custom CSP");
  }
);

5. CSP を Report-Only モードで運用する

本番導入前に CSP の影響範囲を確認したい場合、reportOnly: true を使います。ポリシー違反があってもブロックせず、レポートだけを送信します。

app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'"],
        reportUri: ["/csp-report"],
      },
      reportOnly: true,
    },
  })
);

// CSP 違反レポートを受け取るエンドポイント
app.post("/csp-report", express.json({ type: "application/csp-report" }), (req, res) => {
  console.warn("CSP Violation:", req.body);
  res.sendStatus(204);
});

補足: デフォルトの CSP ディレクティブを取得する

const defaults = helmet.contentSecurityPolicy.getDefaultDirectives();
console.log(defaults);
// {
//   "default-src": ["'self'"],
//   "base-uri": ["'self'"],
//   "font-src": ["'self'", "https:", "data:"],
//   ...
// }

類似パッケージとの比較

パッケージ特徴Express 対応その他のフレームワーク
helmetオールインワンのセキュリティヘッダー設定。最も広く使われている✅ ネイティブ対応Connect 互換ミドルウェアなら利用可
csp-headerCSP ヘッダーの生成に特化。ビルダーパターンで記述ミドルウェアは別途必要フレームワーク非依存
fastify-helmet (@fastify/helmet)Fastify 向けの helmet ラッパー✅ Fastify 専用
koa-helmetKoa 向けの helmet ラッパー✅ Koa 専用
手動設定 (res.setHeader)完全な制御が可能だが、漏れやすく保守コストが高い

Express を使っているなら、helmet が事実上のデファクトスタンダードです。Fastify や Koa を使っている場合は、それぞれ専用のラッパーパッケージを利用してください。

注意点・Tips

⚠️ CSP はアプリに合わせたカスタマイズが必須

デフォルトの CSP は非常に厳格です。Google Fonts、CDN のスクリプト、インラインスタイルなどを使っている場合、そのままではブロックされます。本番投入前に必ず reportOnly モードでテストしてください。

⚠️ Cross-Origin-Embedder-Policy はデフォルトで無効

SharedArrayBuffer などを使う場合に必要な Cross-Origin-Embedder-Policy は、デフォルトでは設定されません。明示的に有効化する必要があります。

app.use(helmet({ crossOriginEmbedderPolicy: true }));

⚠️ Cross-Origin-Resource-Policy が外部からのリソース読み込みをブロックする

デフォルトで same-origin が設定されるため、CDN 経由で画像やフォントを配信している場合、外部サイトから読み込めなくなることがあります。

// CDN として公開する場合
app.use(
  helmet({
    crossOriginResourcePolicy: { policy: "cross-origin" },
  })
);

💡 ミドルウェアの登録順序に注意

helmet はできるだけ早い段階(ルーティングの前)で登録してください。エラーハンドリングのレスポンスにもヘッダーが付与されるようにするためです。

const app = express();

// ✅ 最初に helmet を登録
app.use(helmet());

// その後にルーティングやその他のミドルウェア
app.use(express.json());
app.use("/api", apiRouter);

💡 useDefaults: false でゼロから CSP を構築できる

デフォルトのディレクティブとのマージが不要な場合は、useDefaults: false を指定すると、自分で定義したディレクティブだけが適用されます。

app.use(
  helmet({
    contentSecurityPolicy: {
      useDefaults: false,
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'", "https://cdn.example.com"],
        objectSrc: ["'none'"],
        upgradeInsecureRequests: [],
      },
    },
  })
);

まとめ

helmet は Express アプリのセキュリティ対策として、最初に導入すべきミドルウェアです。app.use(helmet()) の一行で 13 種類のセキュリティヘッダーが設定され、XSS・クリックジャッキング・MIME スニッフィングなどの一般的な攻撃リスクを大幅に低減できます。

特に Content-Security-Policy は強力ですがアプリ固有の設定が必要なため、reportOnly モードで段階的に導入するのがベストプラクティスです。週間ダウンロード数が数百万を超えるデファクトスタンダードであり、Express を使うなら入れない理由はありません。