セキュアアプリケーション・スキャフォルダー は何をしますか?
ANSSI、CIS、FBI、OWASP ASVSレベル2に準拠したセキュアバイデザインのアプリケーションを生成します。TypeScriptフロントエンド、Pythonバックエンド、堅牢化されたPostgreSQLを使用します。
レイアウト、README、UIは project-blueprint スキルに従います。このスキルのセキュリティルールは、利便性やUXに関するルールよりも優先されます。
参考ファイル(該当するアーティファクトを生成する際に参照)
- reference/docker-compose.yml: シークレットブートストラップを含む堅牢化されたComposeファイル。
- reference/nginx.conf: TLS 1.3、ハイブリッドPQ、ヘッダー、レート制限を含むリバースプロキシ。
- reference/security-tests.md: 必須のセキュリティテストマトリックス。
使用タイミング
- 新しいWebアプリケーションやサービスの起動、スキャフォールディング、アーキテクチャ設計時。
- ANSSI、CIS、FBI、OWASP、堅牢化、ルートレス、コンプライアンスに関するリクエストがあった場合。
- 認証、認可、ファイルアップロード、監査ログ、管理機能、デプロイファイル、MCPエンドポイントの追加時。
デプロイ対象: DockerおよびルートレスPodmanのみ。ユーザーが明示的に要求しない限り、Kubernetes、Helm、その他のオーケストレータマニフェストは生成しないでください。
0. 脅威モデル
docs/security/threat-model.md(1ページ以下)を作成します。アセット、信頼境界、アクター、主要リスク(STRIDE)、および各リスクを軽減するコントロールを含めます。新しい信頼境界(アップロード、ウェブフック、LLM、MCP)が現れたら更新します。
1. コンテナとランタイム
- ルートレス: すべてのイメージは数値の
USER(例:USER 10001:10001)で終了します。Webサーバー(nginxinc/nginx-unprivileged、ポート > 1024)も含みます。 - 最小限、ピン留めイメージ: マルチステージビルド。ランタイムステージはdistrolessまたはslimで、シェル、コンパイラ、パッケージマネージャは含みません。開発依存関係は除外。ベースイメージはダイジェストでピン留め。最新の安定版Pythonを使用。
- 堅牢化:
read_only、書き込み可能パスにはtmpfs、cap_drop: [ALL]、no-new-privileges、ランタイムデフォルトのseccompプロファイル(決してunconfinedにしない)、pids_limit、メモリ制限、ヘルスチェック、コアダンプ無効(ulimits: core: 0)。リバースプロキシのみがポートを公開。データベースネットワークはinternal: true。Docker/Podmanソケットは絶対にマウントしない。 - サブプロセスなし:
subprocess、os.system、shell=Trueは使用しない。イメージ内にシェルがないこと、SASTルール、および起動後に各ワーカーにロードされるexecve/execveatを拒否するインプロセスseccompフィルタによって強制されます(コンテナレベルの拒否はエントリポイント自体の起動を妨げる可能性があります)。 - 初回起動保証: クリーンなクローンで、
docker compose up(docker-compose upおよびpodman compose upも同様)が初回で動作すること。.env、手動ステップ、コンテナエンジン以外の前提条件は不要。イメージは自動的にビルド(build:)。Compose Specificationの機能のみを使用し、Docker Compose v2とpodman-composeでサポートされている機能に限定。リポジトリ外のホストパスは使用せず、公開ポートは > 1024。CPU制限は設定しない(多くのルートレスcgroupセットアップでは利用不可)。make upは同じコマンドの薄いラッパーです。 - ハードコードされたシークレットは禁止: ワンショットの
initサービスが、名前付きボリューム(0600)にシークレットを生成し、*_FILE変数を介して利用します。本番環境では、シークレットは環境変数ではなくファイルから読み取られます。 - エアギャップ対応: すべてのJS/CSS/フォント/アイコンはバンドル。CDN、ランタイムダウンロード、テレメトリは使用しません。オフラインビルド時には、依存関係は内部ミラー(Nexus、Artifactory、devpi、Verdaccio)から取得されます。
- Vault対応: 単一のシークレットプロバイダ抽象化(デフォルト
file、本番ではvault/sops)。 - 内部TLS: バックエンド ↔ データベース間はTLS経由。サービス間ではオプションでmTLS。
2. サプライチェーンとスキャン
- ロックされた依存関係: ロックファイルをコミット。
npm ci、uv sync --frozen、またはpip install --require-hashesを使用。.npmrcにignore-scripts=trueを設定(パッケージがインストールスクリプトを必要とする場合を除く。許可リストで管理)。 - ビルド前ゲート:
npm audit --audit-level=highとpip-auditは、終了コードが0より大きい場合にビルドを失敗させます。 - SASTとシークレット: pre-commitで
ruff、bandit/semgrep、eslint(+eslint-plugin-security)、gitleaksを使用。 - イメージスキャン(
make scan):trivy image(CVE + シークレット + 設定ミス)、DockerfileとComposeファイルに対するtrivy config、ベースOSのCISプロファイルに対するoscap-podman(またはoscap-docker)。 - SBOMと署名(
make sbom): CycloneDX SBOM(TrivyまたはSyftを使用)、cosignでイメージに署名(オフラインの場合はキーベース)、SBOMを証明書として添付。デプロイ時に署名を検証。 - DAST(オプション、推奨): CIで実行中のスタックに対してOWASP ZAPベースライン。
- 更新: 定期的な間隔でRenovate/Dependabot(または同等のオフラインレビュー)。
3. フロントエンド(TypeScript)
- 場所:
/frontend。独自のDockerfileを持ち、権限のないNginxによって提供される静的アセットとしてビルド。 - CSP互換コード: インラインの
<script>、eval/new Function、nonceなしで<style>を注入するランタイムCSS-in-JSは使用しない。コンパイル済みCSSを推奨。Trusted Typesを有効にする(require-trusted-types-for 'script')。 - ゼロトラスト入力: フォームごとに型付きZodスキーマを使用し、APIタイプと共有。信頼できないデータには
dangerouslySetInnerHTML/v-htmlを決して使用しない。リッチテキストが避けられない場合はDOMPurifyを使用。 - 冪等性: APIクライアントは、すべてのPOST/PUT/PATCH/DELETEに
Idempotency-Key(UUIDv4)を添付します。これはユーザーアクションごとに1回生成され、リトライ時に再利用されます。 - CSRF: カスタムヘッダー(
X-Requested-With)+ CSRFトークン。バックエンドもOrigin/Sec-Fetch-Siteをチェック。CORS許可リストのみ。資格情報がある場合は*は絶対に使用しない。 - オープンリダイレクト: ログイン後の
next/returnUrlは、単一の/で始まる相対パスのみを受け入れます。 - バンドルにシークレットを含めない。 本番環境ではソースマップなし。
localStorage/sessionStorageに機密データを保存しない。
4. バックエンド(Python)とデータベース
- バリデーション: すべてのボディ、クエリパラメータ、パスパラメータ、ヘッダーは、Pydanticによって最大長と
extra="forbid"でバリデーション(role、owner_id、is_adminなど、入力からバインドできないようにマスアサインメントを防止)。 - リソース制限: 最大リクエストボディサイズ、最大JSON深さ/配列長、最大ページサイズ(例:100)、サーバーサイドタイムアウト。ユーザー入力の正規表現は境界が設定されているか、ReDoSを避けるために線形時間エンジン(
re2)を使用。 - 安全なパース:
pickle、marshal、yaml.load(yaml.safe_loadを使用)、evalは使用しない。XMLはdefusedxmlを使用。テンプレートソースにユーザー入力を含めない(SSTI)。ファイルパスはベースディレクトリに対して解決およびチェック(パストラバーサル対策)。 - 冪等性ストア:
(user_id, key) -> request_hash, status, response、24時間TTL。同じキー + 同じハッシュは保存されたレスポンスを返します。異なるハッシュは422を返します。これにより重複が防止されます。リプレイプロテクションは、TLS、CSRFトークン、短いセッションによって提供されます。 - SQL: ORMまたはパラメータ化クエリのみ。動的な識別子(
ORDER BY、カラム名)は許可リストを通じて使用。 - 列レベルの暗号化: PIIはアプリケーション内でAES-256-GCMで暗号化。エンベロープ暗号化(シークレットプロバイダのマスターキーでラップされたレコードごとのDEK)。ローテーション用の
key_version列。検索可能フィールド用のHMAC-SHA256ブラインドインデックス。マスターキーはDBやDBバックアップに保存されません。 - データベース堅牢化: 最小限のPostgreSQL、
scram-sha-256、TLS、2つのロール(マイグレーション所有者、ランタイムDMLのみ)、アプリからのスーパーユーザーなし、Alembicマイグレーション、ランタイムロールにstatement_timeoutを設定。 - SQLコンソール(ある場合): 読み取り専用ロール、単一の
SELECT、statement_timeout、行制限、ロックされた設定。 - 暗号化と耐量子化: 保存時のAES-256-GCMは耐量子性があります。PQ対応は、鍵交換と署名をターゲットにしています。プロキシ上のハイブリッドTLS
X25519MLKEM768。ML-KEM/ML-DSA(FIPS 203/204)は、ライブラリがサポートしている場合のみ使用。ランダム値はsecrets/crypto.getRandomValuesから取得。暗号プリミティブを自前実装しない。 - アウトバウンドリクエスト(SSRF): UIで設定可能なURL(ウェブフック、syslog、LLM、OIDC)はバリデーション:
httpsのみ(明示的な許可リストがない限り)、解決されたIPがループバック/リンクローカル/メタデータ(169.254.0.0/16、fd00:ec2::254)またはプライベートの場合は拒否(許可リストにない場合)、DNS解決後に再チェック(DNSリバインディング対策)、クロスホストリダイレクトなし、厳格なタイムアウト。 - アウトバウンドウェブフック: HMAC-SHA256(
X-Signature+ タイムスタンプ)で署名。受信者はこれを検証できます。 - メール: ヘッダー値からCR/LFを除去。証明書検証付きSMTPS。
- エクスポート:
=、+、-、@、タブ、CRで始まるCSV/XLSXセルは、'をプレフィックスとして追加(数式インジェクション対策)。 - レート制限: ログイン、パスワードリセット、MFA検証、APIキー、エクスポート、アップロード、および負荷の高いエンドポイント。
- レスポンス: 認証されたAPIレスポンスには
Cache-Control: no-store。request_idを含む一般的なエラーメッセージ。スタックトレースはログのみに出力。本番環境ではOpenAPI UIは無効化、または管理者専用に。
5. 認可
- デフォルトで拒否: すべてのルートは必要な権限を宣言。宣言がないルートは起動時またはテスト時に失敗。
- RBAC: ロールは権限にマッピング(コード内でロールを直接チェックしない)。
- オブジェクトレベルのチェック(IDOR/BOLA): IDによるすべての読み取り/書き込みに対して、リポジトリレイヤーで所有権またはテナントチェックを実行。既存オブジェクトへの不正アクセスは
404を返す。 - 機能レベルのチェック:
/api/v1/admin/*配下の管理者ルートは、単一の依存関係によって保護。UIを隠すだけでは保護しない。 - 機密アクション(ロール変更、キー作成、エクスポート、ユーザー削除)には、最近の再認証が必要。管理者ロールへの昇格にはオプションでフォーアイズ承認。
6. ファイルアップロード(ある場合)
- プロキシとアプリケーションレベルでサイズ制限。拡張子の許可リスト および マジックバイトチェック。
- Webルート外(またはオブジェクトストレージ)に保存。ランダムなファイル名。
Content-Disposition: attachmentとX-Content-Type-Options: nosniffを設定して配信。 - 画像は再エンコード(EXIFとポリグロットを除去)。アーカイブは爆弾とパストラバーサルをチェック。オプションでオフラインのアンチウイルス(ClamAV)。
- SVGとHTMLのアップロードは、サニタイズされ、分離されたオリジンから提供されない限り拒否。
7. ロギング、監査、管理
- 構造化ログ: JSON、レベル DEBUG/INFO/WARN/ERROR/CRITICAL、
request_idをすべてのログに含める。UTCタイムスタンプ。ユーザー値からCR/LFを除去。パスワード、トークン、キー、セッションIDは決してログに記録しない。 - リモートsyslog: TLS経由のRFC 5424(RFC 5425)、ローカルバッファに制限あり。ホスト、ポート、TLS、CAは管理UIから設定可能。rsyslogコンテナは使用しない。
- エラー通知: 管理UIから設定可能なSMTPSとウェブフック。SSRF検証済み。「テスト送信」ボタンあり。スロットル制御あり。
- PIIマスキング: 管理UIから切り替え可能なミドルウェア。
- 改ざん防止監査証跡: 追記専用テーブル(ランタイムロールは
INSERT/SELECTのみ)。各行は前の行のハッシュとチェーン。syslogに転送。サインイン、失敗、MFA変更、ロール変更、設定変更、エクスポート、APIキー、ハニートークンヒットをカバー。ユーザー、IP、ユーザーエージェント、UTC時間、変更前/変更後の値を記録。 - 管理者ダッシュボード: 使用統計、エラー、ハニートークンアラート、ブロックされたIP。
- スケジュールされたハウスキーピング: 非アクティブなアカウントを無効化。期限切れのトークン/セッション/冪等性キーをパージ。毎日の暗号化バックアップ(キーはバックアップと別に管理)。保持ポリシーとテスト済みの復元手順(
make restore-test)。 - 個人データ(GDPR): データタイプごとの保持期間。ユーザーデータのエクスポートと削除。パージジョブ。
8. 認証、アイデンティティ、アクティブディフェンス
- パスワード: Argon2id(argon2-cffiデフォルト / RFC 9106、最小 m=19 MiB、t=2、p=1)。パラメータ変更時にログイン時に再ハッシュ。NIST SP 800-63Bに準拠したポリシー:12文字以上、最大64文字以上、構成ルールなし。バンドルされた漏洩/一般的なパスワードリストに含まれている場合は拒否。
- ログイン: 不明なユーザーに対して同一の応答とタイミング。プログレッシブディレイ + アカウントごとおよびIPごとのスロットル制御(DoSを可能にするハードロックアウトを回避)。
- パスワードリセット: ハッシュ化された使い捨てランダムトークン。30分の有効期限。アカウントの有無にかかわらず同じ応答。リセット後はすべてのセッションを無効化。
- セッション: サーバーサイド。Cookie
__Host-session(HttpOnly; Secure; SameSite=Lax; Path=/)。ログイン時および権限変更時にIDをローテーション。ユーザーはアクティブなセッションを一覧表示および無効化可能。ブラウザストレージにJWTは保存しない。サービス間でJWTを使用する場合:アルゴリズムを固定、noneを拒否、aud/iss/expをチェック、短い有効期間。 - 管理者セッション: 1時間のアイドルタイムアウト。8時間の絶対有効期限。破壊的なアクションには再認証が必要。
- MFA: TOTP(ハッシュ化されたリカバリーコード。同じコードのリプレイは拒否)とWebAuthn/パスキー。管理者アカウントにはMFAが必須。
- コンテキスト検出: 未知のIP/デバイスからの管理者サインインは「新しいサインイン」通知をトリガーし、MFA確認まで破壊的な権限を制限。
- ブートストラップ管理者: 初回起動時にランダムなパスワードを生成。
make admin-passwordで1回だけ読み取り可能。初回ログイン時に強制リセット + MFA登録を要求。 - 緊急時アカウント(オプション): SSOがダウンしているときに使用可能なローカル管理者。デフォルトで無効。使用するたびに重大なアラートが発生。
- SSO: OIDCコードフロー + PKCE。
stateとnonceを検証。IDトークンの署名/aud/issをチェック。証明書検証付きLDAPSまたはStartTLS。LDAPフィルター値をエスケープ(LDAPインジェクション対策)。ディレクトリグループをロールにマッピング。 - SSO設定、2つの同等のソース: すべてのOIDCおよびLDAP(S)設定(有効フラグ、発行元/サーバーURL、クライアントID、スコープ、バインドDN、ベースDN、ユーザー/グループフィルター、CAバンドル、グループ対ロールマッピング、自動プロビジョニング)は、管理UI または 環境変数(
BACKEND_OIDC_*、BACKEND_LDAP_*)のいずれかから設定できます。- シークレット(
client_secret、バインドパスワード)は、*_FILE変数またはシークレットプロバイダから取得。本番環境ではプレーンな環境変数値は使用不可。UIでは書き込み専用(••••last4)。 - 優先順位: 環境変数で定義された設定が優先され、管理UIでは「環境変数で管理」バッジとともに 読み取り専用 で表示されます。それ以外はすべて編集可能で、データベースに暗号化されて保存されます。
- 両方のソースに対して同じバリデーション(環境変数ローダーと管理APIで共有されるPydanticスキーマ)。無効な環境変数設定は、明確なエラーで起動を失敗させます。無効なUI入力は保存前に拒否されます。
- 管理UIには「接続テスト」アクション(OIDCディスカバリ + JWKS取得、LDAPバインド + サンプルグループ検索)があり、すべての変更は監査されます。
- すべての環境変数は、
BACKEND_OIDC_*、BACKEND_LDAP_*というプレフィックスを持ち、make envコマンドで.env.exampleテンプレートとしてエクスポートされます(コメントにデフォルト値と説明付き)。
- シークレット(
- ハニートークン: アプリケーションがファイルシステムおよびデータベースにランダムなハニートークン(APIキー、データベース資格情報、秘密鍵、OIDCクライアントシークレット、セッションCookie)を埋め込みます(ユーザーごとに異なるトークン、難読化されたキー名、アクセス時に管理者アラート、
make honeytoken-reportで確認可能、ルートチェックで見つからない)。 - アクティブディフェンス: このスタックは、一般的なスキャナーと自動化ツールに対して、できるだけ多くの正のシグナル(標準的なエンドポイント、標準的なヘッダー、標準的なテクノロジーフィンガープリント)を 生成する ように設計されていますが、これらはすべてハニートークンで保護されています。
9. 管理者UI
- 場所:
/adminサブドメインまたはパス。 - 機能: ユーザー管理(一覧、作成、無効化、ロール付与、MFAリセット)、ロール管理(権限マッピング)、システム設定(SSO、メール、syslog、通知)、監査ログ(フィルタリング、エクスポート)、セキュリティダッシュボード(脅威メトリクス、最近のブロック、ハニートークンヒット)、メンテナンス(バックアップ、クリーンアップジョブ、復元テスト)、ドキュメント(脅威モデル、セキュリティテスト)。
10. デプロイメントとMakefile
- Makefileターゲット:
up、down、build、logs、ps、shell、db-shell、test、lint、scan(Trivy + OpenSCAP)、sbom、audit(npm + pip)、honeytoken-report、admin-password、backup、restore-test、env(.env.exampleを表示し、存在する場合は.envと比較)、clean(ボリュームを含むダウン、Dockerビルドキャッシュの削除、未使用のイメージ/ボリュームのクリーンアップ、オプションでrm -rfを使用しない一時ディレクトリも削除)。 - クリーンなクローンからの
make upは、.envや手動設定なしで動作すること。
11. 本番前クリーンアップ手順
- デプロイ前に、すべての開発用エンドポイント(
/api/docs、/debug、プロファイリングエンドポイント)が無効化または認証で保護されていることを確認。 - デバッグログレベルを本番レベル(
WARN以上)に設定。 - 一時的な管理者アカウントを削除。
- データベースのマイグレーションが適用されていることを確認。
- 環境変数とシークレット設定を確認。
- セキュリティテストスイート(
make scan、make audit)を実行。 - 署名とSBOMを確認(
make sbom)。 make cleanを実行して未使用のアーティファクトを削除。- 依存関係がロックファイルからインストールされていることを確認(
npm ci、uv sync --frozen)。 make honeytoken-reportを実行してハニートークンが期待通りにデプロイされていることを確認。make restore-testを実行してバックアップ復元手順を検証。
関連スキル
project-blueprint: レイアウト、README、UIの規則について。mcp-server: プロジェクトにMCPサーバーを追加する場合。backend-service: 新しいサービスを追加する場合(各サービスはこのスキルのセキュリティモデルに従う必要があります)。
注記
- セキュリティに関するすべてのルールは、利便性やUXに関するルールよりも優先されます。
- このスキルは、
project-blueprintスキルと一緒に使用することを前提としています。 - このスキルの初期化や設定は必要ありません(
initサービスが初回起動時にすべてを生成します)。 - コード生成時には、可能な限り多くのルールを適用するようにしてください。その完全性は常に確認できません。各リリースでセキュリティテストスイート全体を実行することをお勧めします。