セキュリティ監査チェックリスト
これらのチェックは、システムをプロダクションにリリースする前、または大きな変更を行った後に実行してください。
始める前に
チェックリスト自体は散文であり、特別なものは必要ありません。scripts/ 下の3つのスキャナーはPythonなので、実行するにはマシンに Python 3 が必要です (python3 --version)。Pythonがなくても、チェックリストを手動で進めることは可能です。自動のシークレットスキャン、ヘッダーチェック、IaC読み取りは利用できません。
1. プライバシーとデータガバナンス
- プライバシーポリシーが存在する アプリがユーザーデータを収集、保存、または処理する場合。フッターとサインアップフローにリンクしてください。
- ユーザーデータの保存場所を把握する: プライマリデータベース、キャッシュ、ログ、バックアップ、サードパーティサービスを文書化します。データ保存要件(GDPR、CCPA)を確認します。
- データ最小化: 必要なものだけを収集します。使用しないデータは削除または匿名化します。
2. シークレットとキーの衛生状態
- .envの値が漏洩していない: リポジトリ全体をハードコードされたシークレットがないかスキャンします。
- フロントエンドコードでAPIキーを公開しない: JSバンドルにキーを含めず、パブリックな環境変数プレフィックス (
REACT_APP_、NEXT_PUBLIC_、VITE_) に機密値を入れないでください。 - キーをサーバーサイドまたはプロキシの背後に移動する: シークレットを必要とするすべてのサードパーティAPI呼び出しは、バックエンドエンドポイントを経由する必要があります。
- ログからシークレットを削除する: ログとエラーレポーターからキー、トークン、パスワードをgrepします。出力前にマスキングまたは編集します。
- 漏洩した認証情報は直ちにローテーションする 何か見つかった場合。
クイックスキャンコマンド:
# バンドルされたシークレットスキャナーを実行
python3 scripts/scan_secrets.py .
# 手動ripgrepパターン
grep -rE '(api[_-]?key|secret|token|password)\s*[:=]\s*["\047][a-zA-Z0-9_\-]{16,}' --include='*.{js,ts,py,go,rb,php,java,json,yaml,yml,env,sh,tf,hcl}' .
grep -rE 'AKIA[0-9A-Z]{16}' . # AWSキー
grep -rE 'ghp_[a-zA-Z0-9]{36}' . # GitHubトークン
grep -rE 'sk-[a-zA-Z0-9]{48}' . # OpenAIキー
3. セキュリティヘッダー
-
Content-Security-Policyがスクリプトソースを制限し、可能な場合はインライン実行をブロックしている。 -
X-Frame-Optionsまたはframe-ancestorsがクリックジャッキングを防いでいる。 -
Strict-Transport-SecurityがHTTPSを強制している。 -
X-Content-Type-Options: nosniffが存在する。 -
Referrer-Policyがリファラー漏洩を制限している。
ライブURLのヘッダーを確認:
python3 scripts/check_headers.py https://your-app.com
4. OWASP Top 10の基本
| # | リスク | 確認事項 |
|---|---|---|
| A01 | 破損したアクセス制御 | すべてのエンドポイントが認証と認可をチェックしている。IDORバグがないこと。 |
| A02 | 暗号化の失敗 | パスワードはbcrypt/Argon2でハッシュ化されている。TLS 1.2+が強制されている。URLに機密データがないこと。 |
| A03 | インジェクション | SQLはパラメータ化されたステートメントを使用している。クエリへの生の文字列連結がないこと。 |
| A04 | 安全でない設計 | 認証と機密アクションにレート制限がある。ビジネスロジックに悪用防止策があること。 |
| A05 | セキュリティ設定ミス | デフォルトの認証情報が削除されている。本番環境でデバッグモードがオフになっている。エラーメッセージがスタックトレースを漏洩しないこと。 |
| A06 | 脆弱なコンポーネント | 依存関係監査: npm audit、pip-audit、cargo audit、snyk test。 |
| A07 | 認証の失敗 | セッショントークンはランダムで、権限変更時にローテーションされる。機密アカウントにはMFA。 |
| A08 | データ整合性 | ロックファイルが存在し、可能な場合はコミットに署名されている。 |
| A09 | ロギングの失敗 | セキュリティイベントはシークレットなしで記録される。 |
| A10 | SSRF | サーバーサイドリクエストは許可リストを使用する。内部サービスに到達するユーザー制御のURLがないこと。 |
5. 入力検証とインジェクション
- SQLインジェクション: すべてのクエリがORMパラメータまたはプリペアドステートメントを使用している。
- XSS: ユーザー出力はHTMLエスケープされている。
dangerouslySetInnerHTMLおよび同様のバイパスは監査されている。 - コマンドインジェクション: ユーザー入力による
exec()、system()、またはeval()がないこと。 - パストラバーサル: ファイルパスはサニタイズされ、許可リストディレクトリに制限されている。
- NoSQLインジェクション: MongoDBクエリはパラメータ化されたオブジェクトを使用している。
6. APIセキュリティ
- APIレスポンスに機密データがないか確認: 内部ID、パスワードハッシュ、トークン、不要なPIIがないこと。
- すべての非公開エンドポイントで認証: オープンな管理画面やデバッグルートがないこと。
- 誰かがAPIの課金を燃やす前にレート制限: 高コストまたは認証エンドポイントにIP単位およびユーザー単位のレート制限。
429とRetry-Afterを返す。 - CORSは厳格に:
Access-Control-Allow-Originが*ではないこと。状態変更メソッドにはプリフライトが必要。
7. 認証とセッション
- パスワードポリシー: 最低8文字、パスフレーズを妨げる最大長なし。
- ブルートフォース対策: ログイン失敗後の指数バックオフまたはCAPTCHA。
- セッション管理: secure、httpOnly、SameSiteクッキー。JWTは短い有効期限とリフレッシュローテーション。
- パスワードリセット: トークンは1回限り使用、ランダム、迅速に期限切れ。
8. クラウドプロバイダーのセキュリティ
AWS、GCP、Azure、その他のクラウドプラットフォームに適用されます。
8.1 アイデンティティとアクセス管理 (IAM)
- ルートアカウントのアクセスキーが存在しない。ルートMFAが有効になっている。
- 最小権限の原則: すべてのロール、ユーザー、サービスアカウントが必要最小限の権限を持っている。絶対に必要な場合を除き、ワイルドカード (
*) アクションまたはリソースがないこと。 - ユーザーに長期有効なアクセスキーがない。一時的な認証情報(STS、インスタンスプロファイル、ワークロードID)を持つIAMロールを優先する。
- すべての人間のユーザー、特に管理者と請求アクセスにMFAが強制されている。
- 非アクティブなIDを削除: 90日以上使用されていないユーザー、ロール、サービスアカウントを無効化または削除する。
- クロスアカウントアクセス は、該当する場合は外部IDを使用した明示的なロール引き受けを使用する。
Principal: *を持つ信頼ポリシーがないこと。
8.2 ストレージ (S3 / GCS / Azure Blob)
- パブリックなバケット/コンテナがない 意図的にパブリックな静的アセットをホストしている場合を除く。アカウントレベルでパブリックアクセスをブロックする。
- 保存時の暗号化 が有効 (AES-256またはKMS)。暗号化されていないストレージボリュームやスナップショットがないこと。
- 転送中の暗号化 が強制 (HTTPS/TLSのみ)。
httpは許可されていない。 - ライフサイクルポリシー が古いデータを削除または移行する。重要なバケットではバージョニングが有効。
- バケットポリシー は
Principal: *またはAllUsersを許可していない。アクセスはIAMロールを介して行われ、ハードコードされたキーではない。 - ログ記録が有効 アクセスログとオブジェクトレベルのイベント (S3 Server Access Logs、CloudTrail data events)。
8.3 コンピュート (EC2 / GCE / Azure VM / Lambda / Cloud Run)
- デフォルトのセキュリティグループ が機密ポート (22、3389、3306、5432、6379、27017) で
0.0.0.0/0を許可していない。 - SSM / Session Manager が可能な場合は直接SSHの代わりに使用されている。ポート22がインターネットに公開されていない。
- AWS EC2ではIMDSv2が必要 (IMDSv1を無効にする)。
- インスタンスメタデータ がコンテナや信頼できないコードに公開されていない。
- 関数のランタイム は最小限の権限を使用する。Lambda/GCP Cloud Functionsは管理者ロールで実行されていない。
- 関数の環境変数 に平文のシークレットが含まれていない。シークレットマネージャー (AWS Secrets Manager、GCP Secret Manager、Azure Key Vault) を使用する。
8.4 データベースとキャッシュ
- パブリックアクセスなし: データベースはプライベートサブネットまたはVPC内にある。セキュリティグループに
0.0.0.0/0がないこと。 - 保存時および転送中の暗号化 が有効。
- ポイントインタイムリカバリによる自動バックアップ。
- 強力な認証: デフォルトのパスワードがないこと。サポートされている場合はIAMデータベース認証またはTLSクライアント証明書を使用する。
- 接続とスキーマ変更の監査ログ が有効。
8.5 ネットワーキング
- VPC / ネットワークセグメンテーション: 本番、ステージング、開発は別々のネットワーク、または少なくとも別々のサブネットにある。
- セキュリティグループ / ファイアウォール はデフォルトで拒否。必要なポートのみが開いている。
- 過度に寛容なCIDRなし:
0.0.0.0/0は、パブリック向けロードバランサーのHTTPS (443) を除いて避ける。 - データベース、キャッシュ、内部サービス用のプライベートサブネット。アウトバウンドインターネット用のNAT GatewayまたはVPCエンドポイント。
- DDoS対策 が該当する場合に有効 (AWS Shield、Cloud Armor、Azure DDoS Protection)。
- DNS / ドメイン: レジストラがサポートしていればDNSSEC有効。期限切れのIPや削除されたリソースを指す宙ぶらりんのDNSレコードがないこと (サブドメイン乗っ取りリスク)。
8.6 ロギング、モニタリング、アラート
- CloudTrail / Audit Logs / Activity Logs がすべてのリージョンとサービスで有効。
- ログの整合性: ログは不変であるか、書き込み1回権限を持つ別のアカウントに保存されている。
- 機密データはログに記録されない: クラウドログにパスワード、トークン、PIIが含まれていない。
- アラートが設定されている ルートログイン、IAMポリシー変更、パブリックバケット作成、セキュリティグループ変更、認証失敗の急増に対して。
- ログの保存期間 はコンプライアンス要件を満たす (通常1年)。
9. コンテナとオーケストレーションのセキュリティ
9.1 Docker / コンテナイメージ
- イメージにシークレットがない: Dockerfileとレイヤーを
.env、config.json、またはハードコードされた認証情報がないかスキャンする。 - 最小限のベースイメージ: 可能な場合は、フルUbuntu/Debianの代わりにdistroless、Alpine、scratchを使用する。
- rootで実行しない: Dockerfileで
USERを非rootのUID/GIDに設定する。 - イメージスキャン: レジストリ (ECR、GCR、ACR、Docker Hub) で脆弱性スキャンを有効にし、CIで重大なCVEをブロックする。
- イミュータブルなタグ: 本番環境で
latestを使用しない。ダイジェストまたは特定のセマンティックバージョニングに固定する。 - マルチステージビルド: ビルドアーティファクトと開発依存関係が最終イメージに含まれないようにする。
9.2 Kubernetes
- RBAC: 最小権限のロールとロールバインディング。サービスアカウントにcluster-adminがないこと。
- デフォルトのサービスアカウントトークン は、それらを必要としないポッドにマウントされない (
automountServiceAccountToken: false)。 - ネットワークポリシー: デフォルトでイングレス/エグレスを拒否し、必要なトラフィックのみを明示的に許可する。
- ポッドセキュリティ標準:
restrictedまたはbaselineプロファイルを強制する。特権コンテナ、hostPath、hostNetworkがないこと。 - シークレットの暗号化: etcdの保存時暗号化が有効。Gitに平文のシークレットがないこと。
- コンテナランタイムセキュリティ: seccomp、AppArmor、またはSELinuxプロファイルが適用されている。
- アドミッションコントローラー: OPA/GatekeeperまたはKyvernoを使用してポリシーを強制する (latestタグなし、必須ラベル、リソース制限)。
- リソース制限: すべてのポッドにCPUとメモリの制限があり、リソース枯渇によるDoSを防ぐ。
10. Infrastructure as Code (IaC)
- Terraform / CloudFormation / Pulumi / CDK にシークレットがない: 状態ファイルに平文のパスワードやキーが含まれていない。リモート状態は暗号化され、アクセス制御されている。
- Terraformの状態バックエンド は安全: SSE-KMSを使用したS3、DynamoDBロック、パブリック読み取りアクセスなし。
- IaCスキャン: マージ前にTerraform/CloudFormationで
checkov、tfsec、またはterrascanを実行する。 - ドリフト検出: スケジュールされたスキャンで、IaCから逸脱した手動コンソール変更を検出する。
- モジュールはバージョン固定: ブランチやバージョン管理されていないソースからモジュールをプルしない。
クイックIaCスキャン:
python3 scripts/scan_iac.py .
# またはインストールされている専用ツールを使用:
checkov -d . --framework terraform,cloudformation,dockerfile
# tfsec .
11. CI/CD パイプラインのセキュリティ
- パイプライン設定にシークレットがない:
.github/workflows、.gitlab-ci.yml、Azure Pipelines、Jenkinsfile にハードコードされたトークンがないこと。 - シークレットは注入される CIプラットフォームのネイティブシークレットマネージャー (GitHub Secrets、GitLab CI Variables、Azure DevOps Library) から。
- パイプラインの権限は最小限: CIサービスアカウントはデプロイに必要な権限のみを持つ。
- ブランチ保護: main/masterへの直接プッシュはブロックされる。すべての変更にはPR/MRとレビューが必要。
- 署名付きコミットまたはマージ要件: 機密リポジトリには署名付きコミット、または少なくとも検証済みマージコミットを要求する。
- 依存関係スキャン: SCAツール (Snyk、Dependabot、Renovate) がすべてのPRで実行される。
- SAST: 静的解析 (Semgrep、CodeQL、SonarQube) がすべてのPRで実行される。
- コンテナスキャン: デプロイ前にイメージのCVEがスキャンされる。
- セルフホストランナー がVPNまたはIP許可リストなしでパブリックインターネットに公開されていない。
- パイプラインはフォークからの信頼できないコード を手動承認なしで実行しない (pwnリクエストを防ぐ)。
12. ドメインとDNSのセキュリティ
- DNSSEC がレジストラでサポートされていれば有効。
- 期限切れのサービスを指す宙ぶらりんのCNAME / A / NSレコードがない (サブドメイン乗っ取りリスク)。
- ワイルドカード証明書 または信頼できるCAからのサブジェクトごとの証明書。本番環境で自己署名証明書なし。
- 証明書の有効期限監視: 期限切れの30日前と7日前にアラート。
- CDN / WAF が適切なルール (SQLi、XSS、LFIブロック) で設定されている。エッジでレート制限が有効。
監査出力
チェックリストを実行した後、以下の内容を含む簡潔なMarkdownレポートを作成します:
- サマリー — カテゴリごとに合格/不合格/要レビュー。
- 重大な問題 — 本番環境の前に修正が必要なもの。
- 推奨修正 — 具体的なコード変更、設定更新、またはライブラリアップグレード。
- リスクマトリックス — 各問題に対する可能性 × 影響。
- 改善タイムライン — 優先順位と期限を提案。