mcpField
S
security-checklist

security-checklist

github.com/jamditisセキュリティ438198 回インストール4 日前に更新
リポジトリ

security-checklist について

OWASP Top 10:2025に沿ってアプリケーションを確認する、デプロイ前のセキュリティチェックリストです。各リスクを順に点検し、適用前に最新情報を調べますが、侵入テストや脅威モデリングの代替にはなりません。

主な機能

  1. 01OWASP Top 10:2025に沿った監査
  2. 024つの観点による情報調査手順
  3. 03カテゴリ別のデプロイ確認項目
  4. 04一般的な対策のコード例
  5. 05デプロイ前の25項目チェック

活用シーン

  1. 01本番デプロイ前のアプリ確認
  2. 02アクセス制御や設定の不備の発見
  3. 03依存関係とビルドチェーンの点検

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jamditis/claude-skills-journalism --skill security-checklist

インストール後、Claude Code で/security-checklistを入力して読み込まれたか確認します。

同梱ファイルagents/openai.yamlreferences/agent-pr-review.md

詳細

セキュリティチェックリスト

OWASP Top 10:2025 のカテゴリ(2025年後半に公開され、2021年版の後継となるもの)を軸に整理した、デプロイ前のセキュリティ監査です。これは明らかな重大事故を防ぐための基本であり、本格的なペネトレーションテストや脅威モデリングの代わりにはなりません。このチェックリストを超える検証の深さについては、OWASP ASVS 5.0(https://owasp.org/www-project-application-security-verification-standard/)を参照してください。API 固有の範囲については、OWASP API Security Top 10:2023(https://owasp.org/API-Security/editions/2023/en/0x00-header/)を参照してください。

ステップ 0:最新のセキュリティ動向を調査する(最初に実施)

セキュリティに関する知識の半減期は 6〜12 か月です。以下の手順は 2026-05-08 に最終確認されており、これを読む時点では古くなっている可能性があります。このスキルのパターンを適用する前に、監査対象の OWASP Top 10:2025 カテゴリに絞って調査を並行して行い、このファイルのスナップショットではなく、最新の信頼できる情報に基づいて手順を解釈してください。

原則として実施し、スキップする場合は理由を記録

以下の 4 つの観点からの調査を原則として実施してください。次のすべてに該当する場合に限り、スキップできます。

  • (a) 現在のセッションで、同じ対象について同じスキルを過去 4 時間以内に実行した。
  • (b) そのときの調査で、監査対象の OWASP Top 10:2025 カテゴリに関する緊急性の高い注意情報が見つからなかった。
  • (c) 回答に Research skipped because <reason> という 1 行の注記を記録する。

「知っていると思う」/「急いでいる」/「ユーザーが早く済ませたがっている」/「すでに詳しい」は、スキップする正当な理由ではありません。この前置きの目的は、現在の状況を確認するまでは、このスキル本文の既定の内容を鵜呑みにしてはいけないと、将来の自分に念を押すことです。

4 つのサブエージェントを並行して実行する

各サブエージェントは、引用を含む 300 語以内の箇条書きを返します。4 つすべてを 1 回のメッセージで指示し、並行して実行してください。

観点 1:信頼できる標準。 NIST/OWASP/IETF(RFC および Internet-Draft)/W3C/CISA は、過去 6〜12 か月に、監査対象の OWASP Top 10:2025 カテゴリに関連する新しい情報を公開しましたか?仕様の最終版、廃止、後継仕様、RFC の公開、ドラフトの改訂、NIST SP の更新、OWASP プロジェクトのバージョン更新を調べてください。文書番号と公開日を引用してください。

観点 2:進行中の悪用。 監査対象の OWASP Top 10:2025 カテゴリを狙った、現在悪用されている脅威には何がありますか?CISA Known Exploited Vulnerabilities(KEV)カタログ(過去 6〜12 か月に絞り込み)、CVSS が高い、または実際に悪用されている最近の CVE/GHSA、侵害事例の事後分析やインシデントレポート(CSRB、ベンダーの根本原因分析、セキュリティベンダーの調査)を確認してください。最近 KEV に追加された項目で多く見られる CWE のパターンを示してください。CVE 番号とアドバイザリー URL を引用してください。

観点 3:ツールとライブラリの状況。 このスキルが推奨するライブラリは、現在も最新ですか?関連するパッケージレジストリ(npm/PyPI/RubyGems/crates.io)における最新のメジャーバージョンは何ですか?廃止、置き換え、または別のプロジェクトへの統合はありましたか?安全な既定値に変更はありましたか?現在のバージョンを registry.npmjs.org、pypi.org、rubygems.org、crates.io、pkg.go.dev で確認してください。パッケージ名、バージョン、リリース日を引用してください。

観点 4:実務者の議論。 過去 6 か月に、実務者やセキュリティチームは何を話題にしていますか?OWASP Cheat Sheet Series(最終更新日が重要)、GitHub Security Lab の記事、ベンダーのセキュリティブログ(Cloudflare、Fastly、Snyk、Datadog、Wiz、GitGuardian)、カンファレンストーク(Black Hat、DEF CON、OWASP Global AppSec、USENIX Security)、SANS ISC、Krebs、最近再公開された OWASP プロジェクトの情報を確認してください。採用が進んでいるパターンと、アンチパターンとして指摘されている事例を示してください。記事の URL、著者、日付を引用してください。

レシピを適用する前に統合する

4 件の調査結果がそろったら、「監査対象の OWASP Top 10:2025 カテゴリの本日時点の状況」をまとめた 1 段落を書き、次の点を含めます。

  • 現在の規範上の上限(2026 年に仕様がデフォルトとして SHOULD と定めている内容)。
  • 過去 6〜12 か月に見られた、監査対象の OWASP Top 10:2025 カテゴリに固有の進行中の脅威を 1〜2 件。
  • ツールの変化(非推奨になったライブラリ、フレームワークの新しいデフォルト、統合または置き換えられたパッケージ)。
  • 最近のチートシートやブログの更新に表れている、実務者のコンセンサスの変化。

統合の結果、このスキル本文のレシピに変化があると分かった場合(たとえば、仕様が 2026-05-08 より後に確定した、ライブラリが非推奨になった、デフォルトが変更されたなど)は、回答でその点を明示し、矛盾する箇所はスキル本文の内容を上書きしてください。統合結果が優先されます。スキル本文は足場であり、絶対的な規範ではありません。

サブエージェントを実行できない場合

実行環境でサブエージェントを利用できない場合も、同じ形式でインラインに作業します。対象を絞った検索を 4 回順番に行います(標準の Web 検索、KEV カタログの確認、パッケージレジストリでのバージョン確認、最近のチートシートの差分確認)。同じ 1 段落の統合結果をまとめます。コストは増えますが、保護の水準は変わりません。

このチェックリストの使い方

本番環境へデプロイする前に、10 のカテゴリすべてを確認してください。各カテゴリでは、説明段落を読み、必須項目を確認し、該当する場合はコードパターンの参照先も確認してください。確認後は、不足があるカテゴリごとに 1 件のイシューを起票してください。最後にある 25 項目の Yes/No チェックはデプロイ前の要約であり、監査そのものではありません。

項目を確認できない場合は、デプロイせず、先に修正してください。

A01:2025、アクセス制御の不備

認可の不備は、Web 上で最も悪用されている脆弱性の種類です。2025 年版では SSRF(サーバーサイドリクエストフォージェリ)が A01 に統合されました。根本にある問題が同じ、つまりサーバーが拒否すべきリクエストを処理してしまうことだからです。2024〜2025 年の実例として、API エンドポイントにおけるオブジェクトレベル認可の不備(OWASP API Top 10:2023 の API1 によると、依然として API で最も大きなリスクです)や、クラウドのメタデータエンドポイントを踏み台にする SSRF があります。

  • ゲートウェイやミドルウェア層だけでなく、すべてのエンドポイントで認可を確認する。
  • コントローラー層でデフォルト拒否にする(暗黙の許可ではなく、ルートごとに明示的に許可する)。
  • リソースを取得するたびにオブジェクトレベルの認可を行う(IDOR を防ぐ。プリンシパルが所有していることを確認せずに ID を公開しない)。
  • 管理者用および特権エンドポイントで、機能レベルの認可を行う(ルートだけでなくロールを確認する)。
  • SSRF 対策:サーバー側で URL を取得する場合は、送信先を許可リストで制限する。localhost、127.0.0.0/8、リンクローカル(169.254.0.0/16)、クラウドのメタデータ IP(169.254.169.254)への取得を禁止し、リゾルバーで DNS リバインディングを防ぐ。
  • プラットフォームが対応している場合は、データベースの行レベルセキュリティを有効にする(下記のコードパターンを参照)。
  • アプリケーションでは root/admin ではなく、必要最小限の権限を持つ専用のデータベースユーザーを使用する。
コードパターン:PostgreSQL / Supabase の行レベルセキュリティ
-- Enable RLS on table
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

-- Users can only read their own documents
CREATE POLICY "Users can read own documents" ON documents
  FOR SELECT USING (auth.uid() = user_id);

-- Users can only insert documents as themselves
CREATE POLICY "Users can insert own documents" ON documents
  FOR INSERT WITH CHECK (auth.uid() = user_id);

-- Users can only update their own documents
CREATE POLICY "Users can update own documents" ON documents
  FOR UPDATE USING (auth.uid() = user_id);

-- Users can only delete their own documents
CREATE POLICY "Users can delete own documents" ON documents
  FOR DELETE USING (auth.uid() = user_id);

A02:2025、セキュリティの設定ミス

デフォルトで安全でないフレームワーク設定が本番環境に持ち込まれ続けているため、設定ミスはランキングで順位を上げました(2021年のA05から移動)。2024年のSnowflake/UNC5537キャンペーンは、典型的な教訓です。テナントごとにMFAを有効にするかどうかは、デフォルトでは任意でした。そのため、キャンペーンでは大規模に認証情報が収集され、Snowflakeが2024年にデフォルト設定を変更するまで続きました。

  • 強化済みイメージ/最小構成のコンテナ(distrolessまたはslimベース。必要な場合を除き、シェルなし)。
  • デフォルトの認証情報を削除し、ファイアウォールでデフォルトのポートを閉じる。
  • CORSを特定のオリジン向けに設定する(本番環境でのAccess-Control-Allow-Origin: *は要注意)。
  • Webフレームワークの本番モードフラグを設定する:Flaskではdebug=False、DjangoではDEBUG=False、ExpressではNODE_ENV=production、RailsではRAILS_ENV=production。
  • スタックトレースをクライアントに返さない。
  • クラウドバケット/Blobのパブリック読み取りをデフォルトで無効にし、署名付きURLまたは認証済みリクエストを介してアクセスする。
  • 管理インターフェースをパブリックにアクセスできないようにする(VPN、許可リスト、または認証プロキシを使用)。
  • 不要なサービスとポートを閉じ、ファイアウォールのデフォルト設定を拒否にする。
  • ソースコードやgitの履歴にシークレットを含めず、環境変数またはシークレットマネージャーから読み込む。
  • 開発/ステージング/本番環境ごとに異なるシークレットを使用する。
  • APIキーの権限を必要最小限に設定し、コードをデプロイせずにローテーションできるようにする。
コードパターン:環境変数の設定
# .env (development only, never commit)
# Replace each <placeholder> with a real value generated locally.
# Generate JWT_SECRET with `openssl rand -hex 32` (256 bits).
DATABASE_URL=<your-database-connection-string>
JWT_SECRET=<32-byte-hex-secret>
API_KEY=<api-key-from-your-provider>
# .gitignore (mandatory)
.env
.env.local
.env.*.local
*.pem
*.key
credentials.json
secrets/
// Reading environment variables (Node.js with dotenv)
require('dotenv').config();
const dbUrl = process.env.DATABASE_URL;

// Fail fast if missing
if (!process.env.JWT_SECRET) {
  throw new Error('JWT_SECRET environment variable is required');
}
コードパターン:CORS(Express.js)
const cors = require('cors');

// SAFE: specific origins
app.use(cors({
  origin: ['https://myapp.com', 'https://www.myapp.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
}));

オプションなしのcors()でAccess-Control-Allow-Origin: *を送信する安全でないパターンは、開発環境では問題ありませんが、認証情報を含むリクエストを扱う本番環境では決して使用しないでください。

A03:2025、ソフトウェアサプライチェーンの障害

2025年に新設されたカテゴリで、2021年のA06「脆弱で古いコンポーネント」を統合しています。単なるパッチ適用よりも範囲が広く、SBOM、ビルドシステムの完全性、パッケージの来歴、依存関係のソースに対する信頼性を対象とします。xz-utilsのバックドアCVE-2024-3094(2024年3月)は、「ソーシャルエンジニアリングによってオープンソースのメンテナーが狙われる」ことを示す典型的な教訓です。Polyfill.io(2024年6月)は、「信頼されていたCDNが悪意あるものに変わる」ことを示す典型的な教訓です。

  • ビルド時にSBOMを生成する(CycloneDX 1.7=ECMA-424第2版、2025年12月に批准済み。またはSPDX 2.3以降)。
  • CIで依存関係のスキャンを実行する(Trivy、Grype、Snyk、またはGHSAスキャナー)。重大な問題が見つかった場合は、ビルドを失敗させる。
  • バージョンを固定する(ロックファイルをコミットし、コンテナイメージでlatestのような可変タグや、セキュリティ上重要なライブラリで^x.y.zを使用しない)。
  • 来歴の署名を導入する:npm provenance(2023年9月にGA)、PyPI Trusted Publishing、コンテナ向けのSigstore cosign。
  • SLSA v1.2のソース/ビルドトラックの採用状況を追跡する(2025-11-24リリース、https://slsa.dev/)。
  • スケジュールに従ってパッチを適用する。RenovateまたはDependabotを有効にし、パッチバージョンを自動マージする。
  • サポート終了済みのランタイムを検出して置き換える(Node 18は2025年4月にEOL、Python 3.8は2024年10月にEOL)。
  • すべての外部<script>および<link rel="stylesheet">にSubresource Integrityを設定する(Polyfill.ioの教訓。SRIのチェック項目についてはA08を参照)。

コンプライアンスに関する注記: OMB M-26-05(2026-01-23発行)により、M-22-18およびM-23-16に基づく連邦政府全体のSBOM自己証明義務は撤回されました。EUサイバーレジリエンス法(Reg 2024/2847)の報告義務は2026-09-11から適用され、全面的な義務は2027-12-11から適用されます。米国での撤回を、世界全体での撤回と見なさないでください。

A04:2025、暗号化の失敗

検証済みの高水準ライブラリを使用してください。暗号処理を自作しないでください。AES-CBC + HMAC を手作業で組み合わせず、libsodium、AWS Encryption SDK、または Tink を使用してください。2026 年の規範上の最低基準は、デフォルトで TLS 1.3、最低でも TLS 1.2、TLS 1.0/1.1 は無効化です(RFC 8996 / BCP 195)。

  • HTTPS のみを使用し、HTTP から HTTPS へリダイレクトします。
  • デフォルトで TLS 1.3、最低でも TLS 1.2 を使用し、TLS 1.0/1.1 は無効化します。
  • HSTS preload ヘッダーを設定します:Strict-Transport-Security: max-age=63072000; includeSubDomains; preload(2 年)。
  • Cookie のセキュリティフラグ(Secure、HttpOnly、SameSite=Lax または Strict)を設定します。
  • データベース接続に SSL/TLS を使用します。
  • バックアップを保存時に暗号化し、復元テストを実施します。
  • パスワードの保存には、OWASP のチートシートのパラメーターを使用した argon2id を使用します(m=47104/t=1、m=19456/t=2、m=12288/t=3、m=9216/t=4、または m=7168/t=5。いずれも p=1)。ポリシーの全文は、このバンドル内の secure-auth スキルに記載されています。ここからリンクしてください。
  • 認証または整合性の経路で、MD5、SHA-1、ソルトなしのハッシュを一切使用しません。
  • 暗号処理を自作せず、libsodium、AWS Encryption SDK、Google Tink、または同等のものを使用します。
コードパターン:セキュリティヘッダー(Express.js with Helmet)
const helmet = require('helmet');

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
      frameAncestors: ["'none'"]
    },
  },
  hsts: {
    maxAge: 63072000,
    includeSubDomains: true,
    preload: true
  }
}));
// Manual headers, modern set
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');
res.setHeader('Content-Security-Policy', "default-src 'self'; frame-ancestors 'none'");
// Note: X-Frame-Options is replaced by CSP frame-ancestors. The legacy XSS-protection header is deprecated, modern browsers ignore it.

A05:2025、インジェクション

2024~2025 年の CISA KEV では、CWE-78 の OS コマンドインジェクションが最多を占めており(2024 年は 14 件、2025 年は 18 件)、件数では従来型の SQL インジェクションを上回っています。CWE-22 のパストラバーサルも増加しました(2024 年は 9 件、2025 年は 13 件)。MOVEit CVE-2023-34362 は、SQLi の代表的な事例として今も知られています。

  • すべてのユーザー入力をサーバー側で検証します。クライアント側の検証は UX のためであり、セキュリティ対策ではありません。
  • SQL クエリにはパラメーター化されたステートメントを使用します(CWE-89)。文字列連結は絶対に使用しません。
  • OS コマンドは argv リスト形式で呼び出し、シェルを無効にします。シェル呼び出しで使用するパスやファイル名は、許可リストに基づいて検証します(CWE-78)。
  • LDAP、NoSQL、テンプレートインジェクションにも、同じパラメーター化の原則を適用します。
  • HTML 出力をエスケープします(XSS):フレームワークの自動エスケープに加え、CSP3 nonce と、サポートされている環境では Trusted Types を使用します。
  • ヘッダーインジェクションを防ぐため、レスポンスヘッダーで使用するユーザー入力値を検証します(CR/LF を許可しません)。
  • ファイルアップロードではタイプとサイズを検証し、webroot の外部に保存します。
  • URL とリダイレクト先を許可リストに照らして検証します。
  • JSON/XML パーサーにエンティティ展開の上限を設定します。
コードパターン:パラメーター化 SQL(Node.js)

ユーザー入力を SQL テンプレート文字列に埋め込み、その結果を db.query に渡す安全でないパターンは CWE-89 に該当します。必ずパラメーター化してください。

// SAFE: parameterized query, user input bound as $1
db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
コードパターン:パラメーター化 SQL(Python)
# SAFE: parameterized query, user input bound as %s placeholder
cursor.execute("SELECT * FROM users WHERE id = %s", [user_id])

ユーザー入力を埋め込む f-string で SQL 文字列を構築する安全でないパターンは、CWE-89 に該当します。

コードパターン:コマンドインジェクション(Node.js)

Node の child_process モジュールには、シェル実行プリミティブ(コマンド文字列を /bin/sh 経由で実行するもの)と argv リストプリミティブ(shell: false を指定する spawn 系)があります。ユーザーデータに触れる入力は、すべて argv リストプリミティブを使用してください。

const { spawn } = require('child_process');

// SAFE: argv-list invocation, shell disabled
// userInput is treated as a single argument, never re-parsed by a shell
spawn('convert', [userInput, 'output.png'], { shell: false });

ユーザー入力を埋め込んだテンプレート文字列をシェル実行プリミティブに渡す安全でないパターンは、CWE-78 に該当します。絶対に使用しないでください。シェル機能がどうしても必要な場合は、コマンドの各要素を事前に許可リストに照らして検証してください。

コードパターン:コマンドインジェクション(Python)

Python には、シェル実行プリミティブ(OS のシェル呼び出し関数および subprocess.run(..., shell=True))と argv リストプリミティブ(subprocess.run([...], shell=False))があります。ユーザーデータに触れる入力は、すべて argv リストプリミティブを使用してください。

import subprocess

# SAFE: argv-list invocation, shell disabled
# user_input is treated as a single argument, never re-parsed by a shell
subprocess.run(["convert", user_input, "output.png"], shell=False, check=True)

ユーザー入力を埋め込んだ f-string を OS のシェル呼び出し関数または shell=True の subprocess 呼び出しに渡す安全でないパターンは、CWE-78 に該当します。絶対に使用しないでください。シェル呼び出しに渡す前に、パスやファイル名の各要素を許可リストに照らして検証してください。

コードパターン:XSS(React/フロントエンド)

React は JSX の子要素のコンテンツを自動的にエスケープします。また、このフレームワークには dangerouslySetInnerHTML という、ユーザーデータを渡すと何が起きるかを名前ではっきり警告する prop も用意されています。基本は子要素としてレンダリングし、危険な prop を使うのは、検証済みのサニタイザーを先に通す場合に限ってください。

// DO NOT USE: dangerouslySetInnerHTML on user content with no sanitizer
<div dangerouslySetInnerHTML={{ __html: userContent }} />

// SAFE: React escapes content automatically when rendered as a child
<div>{userContent}</div>

// SAFE: when raw HTML is genuinely required, sanitize through DOMPurify first
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userContent) }} />

サーバーで HTML をレンダリングする場合は、文字列を手作業で組み立てるのではなく、自動エスケープ機能のあるテンプレートエンジン(EJS の <%= %>、自動エスケープを有効にした Nunjucks の {{ }} など)を使用してください。

// DO NOT USE: template-string interpolation of user input into HTML
res.send(`<h1>Hello ${req.query.name}</h1>`);

// SAFE: template engine with auto-escaping
res.render('greeting', { name: req.query.name });

A06:2025、安全でない設計

脅威モデリングとセキュアなデフォルト設定は設計段階で行うべきであり、インシデント発生後に後付けするものではありません。Snowflake の MFA オプトイン方式のデフォルト設定(2024 年まで)は、「セキュアなデフォルト」に関する代表的な教訓です。安全にするためにオプトインが必要な、安全でない状態がデフォルトの機能は、誤用されやすくなります。

  • コードを書く前に、新機能の脅威モデリングを行います(セキュリティには STRIDE、プライバシーには LINDDUN)。
  • ユースケースと併せて、悪用ケースを記述します。
  • 設計レイヤーで最小権限を適用します(サービス、ロール、スコープ)。
  • レート制限は後付けではなく、設計段階で組み込みます。API エンドポイントにはユーザー/IP ごとのレート制限を設定し、ログインエンドポイントにはより厳しい制限を適用し、リクエストサイズの上限を設定し、すべての外部呼び出しにタイムアウトを設定します。
  • アプリケーションの前段に CDN または DDoS 対策を配置します。
  • セキュアなデフォルトを設定します。最も安全な選択肢が最も簡単に選べるようにし、オプトインは安全な選択肢ではなく、安全でない選択肢に適用します。

A07:2025、認証の不備

2021 年の「識別および認証の不備」から名称が変更されました。デフォルト設定はこのバンドル内の secure-auth スキルに記載されています。ここではチェックリスト項目を参照するだけで、重複して記載しません。NIST SP 800-63B-4 は 2025-07-31 に最終版となりました(https://csrc.nist.gov/pubs/sp/800/63/b/4/final)。

  • 単一要素認証のパスワードは 15 文字以上にします(NIST SP 800-63B-4)。文字種の複雑さに関するルールは設けません。定期的な変更も求めません。
  • 登録時/変更時に、漏えいしたパスワードのブロックリストを確認します(Have I Been Pwned API または同等のもの)。
  • パスワードは argon2id でハッシュ化します(代替として、コスト ≥10 の bcrypt、または scrypt も許容されます)。MD5、SHA-1、平文は決して使用しません。
  • すべてのアカウントで MFA を利用できるようにします。AAL3 では、フィッシング耐性のある MFA(WebAuthn/パスキー)が必須です。
  • セッショントークンには暗号学的に安全な乱数を使用します(crypto.randomBytes または同等のもの)。
  • セッションには有効期限を設定します(通常のアプリでは 24 時間、機密データを扱う場合はそれより短くします)。
  • ログアウト時に、サーバー側でセッションを無効化します。
  • パスワードリセットトークンは 1 回限り使用でき、1 時間以内に期限切れとなるようにします。
  • ログイン失敗の試行回数を制限します(例:5 回試行後にクールダウンを設けます)。
  • 権限の変更時(ログイン、ロールの昇格)にセッションを再生成します。
  • リフレッシュトークンをローテーションし、再利用を検知します。
  • 認証情報をコード、ログ、エラーメッセージに含めません。

主な教訓: Change Healthcare(2024 年 2 月、Citrix リモートアクセスのポータルで MFA が未導入、https://www.unitedhealthgroup.com/newsroom/2024/2024-04-22-uhg-update-on-change-healthcare-cyberattack.html)、Snowflake/UNC5537(2024 年、デフォルトで有効な MFA はテナントごとのオプトイン方式)、Storm-0558(2023 年、トークン全体の検証。CSRB のレビューは https://www.cisa.gov/resources-tools/resources/CSRB-Review-Summer-2023-MEO-Intrusion)、23andMe(2023 年、リンクされたアカウントを横断するグラフトラバーサルによる被害範囲)。

A08:2025、ソフトウェアまたはデータの完全性の不備

注:「ソフトウェアまたはデータ」の「または」が重要です。CI/CD パイプラインの完全性、署名付き更新チャネル、デシリアライズの安全性を対象とします。CWE-502(デシリアライズ)は、2024~2025年にKEVを大きく占めています(2024年は11件、2025年は14件)。

  • CI/CD パイプラインの完全性:ビルドへの署名、ブランチ保護、レビューの必須化、パイプライン設定に平文のシークレットを含めない。
  • 更新チャネルの検証:自動アップデーターで署名を検証する。コンテナイメージにはSigstore cosignを使用する。
  • デシリアライズのゲート:信頼できない入力を、ネイティブのバイナリデシリアライザーや、YAMLの制限のないロードプリミティブでデシリアライズしない。信頼境界を越えるデータにはJSONのみを使用する。
  • 外部のすべての<script>および<link rel="stylesheet">にSubresource Integrityを設定する(Polyfill.ioの教訓、https://sansec.io/research/polyfill-supply-chain-attack)。
  • SRIハッシュを固定せずに、CDN上のサードパーティ製スクリプトを参照しない。
  • プルリクエストをレビューするAIエージェントは、PRのファイルを信頼できないデータとして扱い、レビュー規則はベースコミットから取得し、スコープが限定された短命のトークンのみを保持し、コメントのみを投稿します。詳しくはreferences/agent-pr-review.mdを参照してください。
コードパターン:デシリアライズ(Python)

Pythonのネイティブなバイナリデシリアライズプリミティブは、信頼できない入力に対して任意のコードを実行します。loadsはオブジェクトのコンストラクターを実行し、攻撃者が細工した__reduce__ペイロードも実行します。JSONではそのようなことは起きません。あらゆる信頼境界を越えるデータにはJSONを使用してください。YAMLにも同じ危険があります。基本のローダーはPythonコードを実行するため、safe_loadを使用してください。

import json
import yaml

# DO NOT USE: pickle.loads runs arbitrary code on untrusted input,
# any object's __reduce__ method executes at parse time. CWE-502 sink.
#   import pickle
#   obj = pickle.loads(request.body)

# DO NOT USE: yaml.load with no Loader argument is equivalent to yaml.Loader and runs code:
#   config = yaml.load(request.body)

# SAFE: JSON parsing returns plain data (dict / list / str / number / bool / None)
data = json.loads(request.body)

# SAFE: when YAML is genuinely required, use safe_load
config = yaml.safe_load(request.body)

CWE-502(信頼できないデータのデシリアライズ)は、2024~2025年にCISA KEVカタログを大きく占めていました(2024年は11件、2025年は14件)。Java(ObjectInputStream.readObject)、.NET(BinaryFormatter、NetDataContractSerializer、LosFormatter、SoapFormatter)、および任意のオブジェクトを「デシリアライズ」するNodeパッケージにも、同じ警告が当てはまります。信頼境界を越える入力には、JSONのみを安全な選択肢として使用してください。

コードパターン:SRI

<script src="https://cdn.example.com/lib.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

危険なパターンは、integrity属性なしで外部スクリプトを参照することです。これは、CDN上の変更があれば、オリジンのコンテキストで実行されることを意味します。2024年のPolyfill.ioの事例は、まさにこれでした。

A09:2025、セキュリティログ記録とアラートの不備

注:2025年版では「モニタリング」ではなく「アラート」とされ、単なる収集ではなく、積極的な対応を重視する内容に改められています。OktaのHARインシデント(2023年)は重要な教訓です。ログ境界でのサニタイズが不十分だったため、顧客がアップロードしたデバッグ用ファイルに有効なセッショントークンが含まれていました。

  • 認証イベント(ログイン、ログアウト、失敗した試行)、認可の失敗、管理者の操作、支払いイベントを記録する。
  • ログにパスワード、トークン、JWT、APIキー、PII、セッションID、クレジットカード情報、またはユーザーデータを含むリクエスト本文全体を含めない。
  • 保持ポリシーを定めた一元的なログ記録を行う(セキュリティログは最低90日間、コンプライアンス対応のためにはさらに長期間)。
  • ログを安全に保存する(保存時に暗号化し、アクセスを制御する)。
  • 不可能な移動、大量の認証失敗、権限昇格のパターンに対するアラートを設定する。
  • エラーメッセージからクライアントにシステム情報が漏れないようにする(A10を参照)。

重要な教訓: Okta HARファイルのインシデント、https://sec.okta.com/articles/harfiles/

コードパターン:記録してはいけないもの
// SAFE: structured logging with field allowlist
console.log('Login attempt:', { email, success: false, reason: 'invalid_password' });
console.log('Request:', { endpoint: req.path, method: req.method, userId: req.user?.id });

危険なパターンは、リクエスト本文全体や認証情報オブジェクトを記録することです。これにより、ユーザーが入力したすべてのシークレットが漏えいします。パスワードフィールド、トークンフィールド、リクエスト本文全体、セッション識別子は、決してログに記録しないでください。

A10:2025、例外条件の不適切な処理

2025年に追加された新しいカテゴリです。CWEカタログでは、24個のCWEのうちCWE-209/234/274/476/636を対象として、このカテゴリにCWE-1445が割り当てられています。2024年7月のCrowdStrike Channel File 291インシデントは、教訓の基準となる事例です。未検証の構成ファイルを本番環境にデプロイした結果、850万台のWindowsホストでBSODが発生しました。

  • セキュリティに関わるコードパスでは、デフォルトでフェイルクローズにします(認証/認可/完全性の障害時に、すべてを捕捉して処理を続行しないでください)。
  • エラーレスポンスから、構造、スタックトレース、内部IDが漏えいしないようにします。
  • 本番環境へのデプロイ前に構成を検証します。段階的なロールアウト、カナリアリリースの割合設定、ステージング環境と本番環境の間の検証ゲートを設けます。
  • Exception ブロックで、セキュリティに関わる障害を黙って握りつぶさないようにします。
  • 例外パス(タイムアウト、OOM、部分書き込み、ネットワーク分断)をテストします。セキュリティ回帰の多くは、ここに潜んでいます。
  • すべての外部呼び出しにタイムアウトを設定し、タイムアウト発生時の処理を明示します。

教訓の基準となる事例: CrowdStrike Falcon Channel File 291の根本原因分析(RCA)、https://www.crowdstrike.com/en-us/blog/falcon-content-update-preliminary-post-incident-report/

デプロイ前の概要、25項目のYes/Noゲート

監査の最後に実施してください。回答が1つでもNの場合は、リリースしないでください。

  1. TLS 1.3が強制されている(TLS 1.2を最低バージョンとし、1.0/1.1は無効)? Y/N
  2. max-age=63072000; includeSubDomains; preload を指定したHSTS preloadヘッダーが設定されている? Y/N
  3. パスワードのハッシュ化にargon2id(またはコスト係数10以上のbcrypt/scrypt)を使用している? Y/N
  4. パスワードの最小文字数が15文字で、文字種の組み合わせルールや定期変更を要求していない? Y/N
  5. すべてのアカウントでフィッシング耐性のあるMFAを利用できる? Y/N
  6. セッショントークンは暗号学的に安全な乱数で生成され、ログアウト時に無効化される? Y/N
  7. すべてのSQLクエリでパラメーター化を使用している? Y/N
  8. OSコマンドでargvリスト形式を使用し、シェルを無効にしている? Y/N
  9. HTML出力が自動エスケープされ、frame-ancestors を含むCSPが設定されている? Y/N
  10. CORSが特定のオリジンに限定されている(本番環境で * を使用していない)? Y/N
  11. コントローラーレベルでデフォルト拒否の認可を設定している? Y/N
  12. リソースを取得するたびにオブジェクトレベルの認可を行っている(IDORがない)? Y/N
  13. SSRF対策として、送信先の許可リストとメタデータIPのブロックリストを設定している? Y/N
  14. 対応している箇所で、データベースの行レベルセキュリティを有効にしている? Y/N
  15. コードやgit履歴にシークレットがなく、すべて環境変数/シークレットマネージャーから読み込んでいる? Y/N
  16. 本番モードのフラグを設定している(debug=False、NODE_ENV=production など)? Y/N
  17. スタックトレースをクライアントに返さない? Y/N
  18. ビルド時にSBOMを生成し、CIでスキャンしている? Y/N
  19. すべてのサードパーティ製スクリプトで、SRIハッシュを固定している? Y/N
  20. ロックファイルで依存関係を固定し、コンテナタグに浮動タグを使用していない? Y/N
  21. サポート終了済みのランタイムにフラグを立て、置き換えている? Y/N
  22. 認証イベント、認可の失敗、管理者操作を(シークレットを含めずに)ログに記録している? Y/N
  23. 認証失敗の大量発生と権限昇格に対するアラートを設定している? Y/N
  24. セキュリティに関わるコードパスがフェイルクローズになっている? Y/N
  25. 構成を検証し、段階的デプロイでロールアウトしている? Y/N

インシデント対応のクイック修正

「パスワードを平文で保存していました」
  1. すぐにパスワードのハッシュ化を追加します(argon2id。secure-auth スキルを参照)。
  2. すべてのユーザーにパスワードのリセットを強制します。
  3. 既存のすべてのセッションを無効化します。
  4. 漏えいの兆候を確認します(データベースが公開されたことや、安全でない方法でバックアップされたことはありますか?)。
「APIキーがgit履歴に含まれています」
  1. すぐにキーをローテーションします(新しいキーを生成します)。
  2. 古いキーを失効させます。
  3. git filter-repo(git filter-branch より推奨)またはBFG Repo-Cleanerを使って、履歴から削除します。
  4. 強制プッシュし、チームと調整します。
「どのデータをログに記録しているかわかりません」
  1. コードベース内で console.log、logger.、print( を検索します。
  2. ログに記録されている内容を確認します。
  3. フィールド許可リストを使った構造化ログを実装します。
  4. ログのローテーションと保持期間を設定します。
「データベースがインターネットからアクセス可能です」
  1. すぐにデータベースの認証情報を変更します。
  2. ファイアウォールルールを設定します(アプリケーションサーバーのIPのみを許可します)。
  3. 接続でSSL/TLSを有効にします。
  4. 不正なクエリがないか、アクセスログを確認します。

コンプライアンスのクイックリファレンス

以下の規制や基準への対応が必要になる可能性があります。

  • GDPR(EU のユーザー):データ削除の権利、同意、侵害通知。
  • CCPA(カリフォルニア州のユーザー):GDPR と類似しています。
  • PCI DSS(クレジットカード):カード番号を保存せず、決済処理業者を利用してください。
  • HIPAA(医療データ):暗号化、アクセス制御、監査ログ。
  • SOC 2(エンタープライズ向けの営業):セキュリティ管理策の文書化。
  • SEC Form 8-K Item 1.05(米国上場企業):重大なサイバーセキュリティインシデントは、4 営業日以内に開示する必要があります(2023-12-18 施行)。
  • EU Cyber Resilience Act(Reg 2024/2847):デジタル要素を含む製品が対象です。報告義務は 2026-09-11 から、義務全体は 2027-12-11 から適用されます。
  • OMB M-26-05(米国連邦政府のサプライヤー):政府全体に適用される SBOM 自己証明の義務が撤回されました(2026-01-23 発行)。各機関固有の要件は引き続き適用される場合があります。

ユーザーデータを扱う場合の最低限の要件:

  1. データ収集について説明するプライバシーポリシー。
  2. ユーザーがデータ削除をリクエストできる手段。
  3. 通信時(HTTPS)および保存時の暗号化。
  4. アクセスログと監査証跡。
  5. インシデント対応計画(基本的なものでも構いません)。

参考ファイル

コーディングエージェントを使ってプルリクエストをレビューするボットを構築または監査する場合は、プルリクエストレビュアーとして AI エージェントを運用するをお読みください。

リソース

標準規格とフレームワーク
脆弱性データ
サプライチェーン
インシデントに関する参考資料
コンプライアンス
テストツール

コメント