メインコンテンツへスキップ
友田 陽大
アプリ層セキュリティ
Next.js
セキュリティ
アーキテクチャ設計
TypeScript

セキュリティをCIで止める — GitHub Actions・SARIF・『高確度のみブロック』の設計

セキュリティ検査をCIに組み込み、高確度の検出だけでビルドを止める設計。GitHub ActionsでのSAST実行、SARIFによるコードスキャニング連携、誤検知でCIを壊さない(静的×動的の相関で確証のみブロック)運用を、実際のYAMLとコマンドで解説します。

公開日
読了時間
23分
著者
友田 陽大
シェア

最初に結論を述べます。セキュリティ検査は「人が思い出したときに手元で走らせるもの」である限り、いつか必ず忘れられます。 価値を生むのは、PRを開いた瞬間にCIが自動で走り、高確度の脆弱性だけがマージをブロックする仕組みにしたときだけです。本記事は、その仕組みを GitHub Actions と SARIF で組む方法を、実際のYAMLとコマンドで示します。

ただし、もう一つ最初に正直に言っておきます。CIゲートはセキュリティの"仕組み化"であって、設計レビューや手動監査の代わりにはなりません。 ツールは「よくある罠を踏んでいないか」を機械的に番をするだけで、あなたの認可ロジックが「正しいか」は証明しません。本記事が扱うのは、その境界を踏まえたうえで——自動化できる検査を、誤検知でCIを壊さずに、継続運用の歯車として組み込む設計です。


1. なぜ「PRで止める」のか——シフトレフトの経済学

脆弱性は、見つかるのが遅いほど直すコストが跳ね上がります。

見つかるタイミング状態直すコスト
コーディング中(手元)まだコミットしていないほぼゼロ。書き直すだけ
PRレビュー(CI)マージ前。差分が小さい低い。文脈が新鮮なうちに直せる
本番リリース後デプロイ済み・データに影響高い。調査・パッチ・場合により事故対応
インシデントとして発覚漏洩・悪用が進行最悪。信頼の損失まで含む

「シフトレフト(shift left)」とは、この表の上の方——できるだけ**左(=開発の早い段階)**で問題を潰す思想です。CIにセキュリティ検査を入れる本質は、ここにあります。本番に出た脆弱性を後から探すのではなく、PRの時点で「そもそもマージさせない」。

重要なのは、これが人間の規律に依存しない点です。「コミット前にスキャンを忘れずに」という運用は、忙しい日に必ず破られます。一方、CIゲートは忘れようがない——PRを開けば自動で走り、赤ければマージボタンが押せない。セキュリティを「気をつける」から「構造で強制する」へ移すのが、CIゲートの第一の価値です。

この発想は、セキュリティに限らずAI生成コード全般の品質統制と地続きです。型・テスト・セキュリティをCIで束ねる考え方はAI駆動開発の品質ゲート設計に整理しました。本記事はその「セキュリティ検査の歯車」を、SARIFとGitHub Actionsで具体化したものです。

なお、何を自動化で潰し、何を設計で守るのか——という全体地図はNext.js × Supabase アプリケーションセキュリティ完全ガイドにまとめています。本記事はそこで言う「水平統制・注入クラスの検出をCIに常設する」部分の実装編です。


2. SARIFとは何か——「検査結果」の共通言語

CIでセキュリティ検査を回すとき、最初にぶつかる問題があります。ツールごとに出力フォーマットがバラバラだということです。あるツールはJSON、別のツールはテキスト、また別のはJUnit XML——これではGitHubのUIに統一して表示できず、ツールを乗り換えるたびに連携を書き直すことになります。

ここで効くのが SARIF(Static Analysis Results Interchange Format) です。SARIFは、OASISが標準化した静的解析結果を表現するためのJSONベースの標準フォーマットです(OASIS SARIF v2.1.0)。どんなSASTツールでも、結果をSARIFで吐けば、それを受け取る側(GitHub等)は中身を統一的に扱えます。

SARIFの最小構造は、ざっくりこうです。

// SARIF v2.1.0 の骨格(型のイメージ)。実際のファイルはツールが生成する
type Sarif = {
  version: "2.1.0";
  runs: Array<{
    tool: { driver: { name: string; rules: Array<{ id: string }> } };
    results: Array<{
      ruleId: string;                 // どの検査ルールに当たったか
      level: "error" | "warning" | "note"; // 深刻度 → CIの赤/黄を決める
      message: { text: string };      // 人間が読む説明
      locations: Array<{              // どのファイルの何行目か
        physicalLocation: {
          artifactLocation: { uri: string };
          region: { startLine: number };
        };
      }>;
    }>;
  }>;
};

ポイントは3つです。

  1. ruleId — どの検査に引っかかったか。GitHub上でルール単位の集計・抑制ができます。
  2. levelerror / warning / note。これがCIで何を赤にし、何を黄色(警告)に留めるかの根拠になります。後述の「高確度のみブロック」は、ここをどう割り当てるかの設計です。
  3. locations — ファイルと行番号。これがあるから、GitHubはPRの差分に行単位の注釈を打てます。

つまりSARIFは「検査結果の共通言語」です。ツールを乗り換えてもCI連携はそのまま、UIへの表示もそのまま。検査ロジックと表示・運用を疎結合にできるのが、標準フォーマットを使う最大の利点です。


3. GitHub コードスキャニングに載せる——差分注釈とSecurityタブ

SARIFを吐けたら、次はそれをGitHubに食わせます。GitHubには コードスキャニング(code scanning) という機能があり、SARIFをアップロードすると2つの場所に結果が現れます(GitHub code scanning docs)。

  • Security タブ — リポジトリの全アラートが一覧化され、ルール別・深刻度別に管理できる。既知の指摘を「無視(dismiss)」したり、再発を追跡したりできる。
  • PRの差分(Files changed) — 検出された行にインラインの注釈が付く。レビュアーは「この変更がこの脆弱性を入れた」を、コードを読みながらその場で見られる。

この「PRの差分に注釈が出る」体験が決定的です。セキュリティの指摘が、別のダッシュボードや週次レポートではなく、まさにレビューしているコードの横に出る。直す文脈が新鮮なうちに、最小の差分で直せます。第1節のシフトレフトを、UIのレベルで実現するのがコードスキャニングです。

GitHubが受け取るのはあくまでSARIFなので、ここでも特定ツールへのロックインはありません。SARIFさえ吐ければ、自作ツールでもOSSでも、同じレールに載ります。


4. 実YAML——GitHub ActionsでSASTを走らせ、SARIFを上げる

ここからが実装の中心です。私が公開しているOSSセキュリティスキャナ Aegis には GitHub Action が同梱されており、uses 一行でCIに組み込めます。Aegisは Next.js × Supabase の注入クラス(汚染入力→危険シンク)やRLS/認可の弱点を検出し、結果をSARIFで出力します。

以下を .github/workflows/security.yml に置くだけで、push と PR のたびにスキャンが走り、結果がコードスキャニングに載ります。

# .github/workflows/security.yml
name: Security
on: [push, pull_request]

jobs:
  aegis:
    runs-on: ubuntu-latest
    permissions:
      contents: read          # コードを読むためだけの最小権限
      security-events: write  # SARIF を Security タブへアップロードするのに必須
    steps:
      - uses: actions/checkout@v4

      - uses: tomodahinata/aegis@main
        with:
          severity: HIGH       # HIGH 以上だけを「赤(ブロック)」に昇格させる

      - uses: github/codeql-action/upload-sarif@v3
        if: always()           # スキャンが失敗しても結果は必ずアップロードする
        with:
          sarif_file: aegis.sarif

短いですが、設計上の判断が4つ詰まっています。順に解きます。

4-1. permissions は最小権限で固定する

ワークフローに与える権限は、必要なものだけに絞ります。

  • contents: read — リポジトリのコードを読むため。書き込みは不要なので read
  • security-events: write — SARIFをアップロードしてコードスキャニングのアラートを作るのに必須の権限です。これが無いと upload-sarif が失敗します。

ここで write を広げすぎない(例えば contents: write を付けない)のは、CIワークフロー自体が攻撃面だからです。サプライチェーン攻撃では、過剰な権限を持つワークフローが踏み台にされます。最小権限の原則(OWASPのApplication Security Verification Standardが一貫して説く思想)は、アプリのコードだけでなくCIの設定そのものにも適用します。

4-2. if: always() で「結果は必ず上げる」

upload-sarif のステップに if: always() を付けています。これは、前のスキャンステップが「脆弱性あり」で失敗(exit 1)しても、SARIFのアップロードは実行するためです。

これが無いと、こういう最悪の挙動になります——「HIGHの脆弱性が見つかってスキャンが赤くなった」→「ジョブが止まってアップロードがスキップされる」→「一番見たい指摘がコードスキャニングに載らない」。ブロックすることと、指摘を可視化することは別の関心事です。always() で後者を必ず保証します。

4-3. severity: HIGH が「ブロックの閾値」

with: severity: HIGH が、本記事の核心である**「高確度のみブロック」の入口**です。これは「HIGH以上の確度・深刻度を持つ検出だけを、CIを赤にする(マージをブロックする)対象にする」という指定です。MEDIUM以下は——後述しますが——SARIFには載せてコードスキャニングで見えるようにしつつ、ビルドは止めない(警告に留める)運用が基本になります。

なぜこの閾値設計が決定的なのかは、次節で詳述します。

4-4. Action 参照は tomodahinata/aegis@main

uses: tomodahinata/aegis@main は Aegis Action の正しい参照です。v1 のようなタグはまだありませんので、@main を使ってください。本番運用でバージョンを固定したい場合は、@main の代わりにコミットSHAでピン留めする(tomodahinata/aegis@<commit-sha>)のが、サプライチェーン的には最も安全です(タグやブランチは動きうるが、SHAは不変)。


5. ノイズ問題——「誤検知でCIを壊す」と、ゲートは無視される

ここが、CIセキュリティで最も多くのチームが失敗するポイントです。技術的な難しさではなく、運用の力学の問題です。

セキュリティゲートを入れた直後、ツールが大量の指摘を吐いたとします。その多くが誤検知(false positive)——実際には悪用できない、文脈的に問題ない指摘だったとします。すると何が起きるか。

  1. PRが毎回赤くなる。しかも理由の大半が「直す必要のない指摘」。
  2. 開発者は「またノイズか」と赤を信用しなくなる
  3. やがて誰かが「とりあえず通すために」ゲートを continue-on-error にするか、ジョブごと無効化する。
  4. セキュリティゲートが死ぬ。 本物の脆弱性も一緒にすり抜けるようになる。

これは仮想の話ではなく、CIセキュリティ導入の典型的な失敗曲線です。「厳しすぎるゲートは、必ず迂回される」。狼少年と同じで、嘘の警報が続けば、本物の警報も無視されます。

ここから導かれる原則は一つです。

CIをブロックする検出は、誤検知率が極めて低いものに限定する。 残りは「警告として見せる」に留め、ビルドは止めない。ゲートの信頼は「赤が出たら本当にヤバい」という体験でしか育たない。

問題は、「どうやって誤検知率の低い検出だけを選り分けるか」です。深刻度(severity)が高い=確度が高い、ではありません。「これはSQLインジェクションかもしれない」という静的解析の"疑い"は、深刻だが不確実です。この不確実性をどう潰すか——それが次節のSAST×DAST相関です。


6. 高確度のみブロック——静的の"疑い"を動的で"確証"に格上げする

「高確度だけをブロックする」を実現する鍵は、確度の出どころを二重化することです。一つの静的解析だけで「これは確実」と断ずるのは難しい。だから、静的解析(SAST)の疑いを、動的プローブ(DAST)で実際に再現できたかで格上げします。

6-1. 二段階の確度モデル

SAST(静的解析)        :コードのデータフローを追い、「汚染入力→危険シンク」を疑う
   ↓ 疑い(potential)
DAST(動的プローブ)     :自分のアプリを実際に叩き、その疑いが再現するか確かめる
   ↓ 再現できた
confirmed(確証)       :静的×動的が一致 → これだけを CI でブロックする
  • SASTは「疑う」。第2のガイドで詳述した「params.id が所有権チェックなしでDBクエリに届く」ようなパターンを、関数内のtaint解析で機械的に拾います。これは速くて網羅的ですが、文脈次第で誤検知も出る(例:別の場所で実は絞り込まれている)。
  • DASTは「再現する」。自分が所有するアプリに対して、2つのアイデンティティ(A・B)を用意し、Aのセッションのまま Bのリソースを叩く——といった安全・非破壊なプローブを実行します。200が返って他人のデータが見えたら、その疑いは実行時に確証されます。

そして、SASTの疑いとDASTの再現が一致したものだけconfirmed-exploitable(確証済み)として、SARIFの level: "error" = CIブロック対象に昇格させます。再現できなかった静的の疑いは warningnote に留め、コードスキャニングには出すがビルドは止めない

これが「高確度のみブロック」の実体です。深刻度の高さではなく、"動的に再現できた"という事実を、ブロックの根拠にする。

6-2. ローカルでの相関——CIに入れる前に手で確かめる

CIに組み込む前に、まず手元でこの相関を体感しておくとよいです。Aegisはスキャンとプローブを別コマンドで提供しています。

# 1. 静的解析:汚染入力→危険シンク/所有権なしクエリを「疑う」
npx @aegiskit/cli scan

# 2. 動的プローブ:自分のアプリを実際に叩き、疑いが「再現するか」確かめる
#    --correlate で静的の結果と突き合わせ、再現したものを confirmed に格上げ
npx @aegiskit/cli probe http://localhost:3000 --correlate

--correlate を付けると、scan の疑いのうち probe で再現したものが確証済みとしてマークされます。この「確証済みだけが赤」という体験を手元で作っておくと、CIに severity: HIGH で入れたときの赤の意味が腑に落ちます。

プローブの倫理的境界。 DASTは自分が所有・管理するアプリに対してのみ実行してください。他人のサービスへの無許可のプローブは攻撃と区別がつかず、法的にも問題になります。Aegisのprobeは非破壊(読み取り中心、データを壊さない)設計ですが、対象は必ず自分のステージング/ローカルに限ります。


7. 段階導入——いきなりブロックしない(warn → block)

「高確度のみブロック」を設計しても、初日からブロックを有効にするのは悪手です。既存のコードベースには、まず確実に**過去分の指摘(ベースライン)**が溜まっています。それを全部ブロックにすると、関係ない人のPRまで赤くなり、第5節の「ゲートが死ぬ」曲線に乗ります。

正しい順序は、warn から始めて、信頼が育ってから block に上げるです。

段階1:警告のみ(ビルドは止めない)

まずは「結果を可視化するが、ブロックはしない」状態から始めます。スキャンステップに continue-on-error: true を付け、SARIFのアップロードだけ確実に行います。

# 段階1:warn のみ。指摘は Security タブと差分注釈に出すが、CI は赤にしない
- uses: tomodahinata/aegis@main
  with:
    severity: HIGH
  continue-on-error: true   # ← 検出があってもジョブを失敗させない(観察期間)

- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: aegis.sarif

この期間に、チームは「どんな指摘が出るか」「どれが本物でどれがノイズか」を学びます。既存の確証済み指摘は、この間にPRで潰すか、後述の抑制で正式に「無視」を記録します。

段階2:高確度だけブロックに昇格

ベースラインが片付き、ノイズの傾向が掴めたら、continue-on-error を外してブロックを有効化します。

# 段階2:confirmed(HIGH かつ動的再現済み)だけがビルドを止める
- uses: tomodahinata/aegis@main
  with:
    severity: HIGH
  # continue-on-error を外す → HIGH 検出でジョブが失敗=マージ不可になる

- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: aegis.sarif

仕上げに、GitHubのブランチ保護ルールSecurity チェックを「マージ必須」に指定します。これで「赤いPRは構造的にマージできない」状態が完成します。警告から始め、確証だけをブロックに昇格させる——この順序が、迂回されないゲートを作る唯一の現実的な道です。


8. 鍵レス運用(OIDC)——CIに長期シークレットを置かない

CIセキュリティを語るうえで、CI自身のシークレット管理に触れないわけにはいきません。ゲートを守るワークフローが、鍵の漏洩経路になっては本末転倒です。

ここまでのAegis Actionの例は、外部サービスへの認証を必要としません(コードを読んでSARIFを出すだけ)。security-events: writeGITHUB_TOKEN の自動権限で賄われ、長期シークレットは不要です。これ自体が良い設計です。

一方で、CIから外部(クラウドやコンテナレジストリ等)にアクセスする必要が出たときは、長期のアクセスキーをリポジトリのSecretsに置かないのが鉄則です。代わりに OIDC(OpenID Connect) を使い、ジョブ実行時にだけ有効な短命のトークンを発行して認証します。

# OIDC で短命トークンを取得する例(クラウド連携が必要な場合)
permissions:
  contents: read
  id-token: write   # ← OIDC トークンの発行に必要。長期キーは Secrets に置かない

id-token: write は、ワークフローが自身のIDを証明する短命トークンを取得する権限です。これをクラウド側の信頼設定(特定リポジトリ・特定ブランチからのみ受け付ける)と組み合わせると、漏れて困る長期鍵がそもそも存在しない状態になります。これも最小権限・最小有効期間の徹底です。

環境変数とシークレットの境界設計そのもの——どこまでをコードに出し、何を秘匿し、いつ起動時検証するか——は、本記事の主題から外れるため別途まとめています(Next.js × Supabase アプリケーションセキュリティ完全ガイドの「型付きenv境界」を参照)。


9. RLS/認可の回帰もCIで——SQL検証を相関に足す

注入クラスの検出(SAST)と動的プローブ(DAST)に加えて、SupabaseのRLS/認可の設計そのものもCIで検証できます。これは「相関」の第3の軸です。

Aegisのスキャンは supabase/migrations/**.sql を読み、RLS無効のテーブル、using (true) の無条件許可、WITH CHECK 欠落、search_path 未固定の SECURITY DEFINER 関数、anonロールへの過剰GRANTといった構造的な弱点を検出し、これもSARIFに含めます。RLSの設定ミスの体系的な検出観点はRLS設定ミスの検出と監査に詳しくまとめています。

さらに退行を防ぐなら、pgTAPでRLSの回帰テストを書き、CIで「他人の行が見えないこと」を継続的に証明します。これはSARIFとは別系統(テストの赤/緑)ですが、同じCIパイプラインで束ねる価値があります。

-- pgTAP:別ユーザーのJWTで他人の行が見えないことを回帰テストにする
begin;
select plan(1);
set local role authenticated;
set local request.jwt.claims to '{"sub":"user-b-uuid"}';
select is_empty(
  $$ select * from invoices where user_id = 'user-a-uuid' $$,
  'user B cannot read user A invoices'
);
select * from finish();
rollback;

こうして**SAST(コード)・SQL検証(RLS設計)・DAST(実行時再現)・pgTAP(回帰)**の4つを同じCIで回し、確証が取れたものだけをブロックに昇格させる——これがCIセキュリティの完成形です。注入や認可がOWASPのOWASP Top 10で繰り返し上位に並ぶのは、これらが最も普通に混入するからこそ。だからこそ「人が気をつける」ではなく「CIが番をする」価値があります。


10. 正直なスコープ——CIゲートは監査の"代わり"ではない

ここは本記事で最も強調したい点です。CIゲートは、設計レビューや手動監査を置き換えません。

CIに常設できるのは、本質的に**「機械的に判定できるパターン」です——汚染入力が危険シンクに届いているか、RLSが無効になっていないか、所有権チェックが構文的に抜けていないか。これらは価値ある検査ですが、見ているのはあくまでコードとSQLの"形"**です。

一方、「この認可ロジックは事業ルールとして正しいか」「このテナント帰属の根拠(app_metadatauser_metadata か)は妥当か」「この状態遷移はありえない順序を許していないか」——こうした判断は、あなたのデータモデルと事業の意味を理解した人間にしか下せません。CIゲートがどれだけ緑でも、それは「よくある罠は踏んでいない」を意味するだけで、「認可が正しい」を意味しません。

いかなるツールも、認可の"正しさ"は証明しない。 データフロー解析は関数内(intraprocedural)が基本で、モジュールやフレームワークを跨ぐ流れは見逃します。動的プローブも「試した経路で再現しなかった」だけで「安全」ではありません。CIゲートは継続運用の"仕組み化"であり、人間のレビューと脅威モデリングを補完するもの——置き換えるものではありません。

この線引きを踏まえると、CIゲートの正しい役割が見えます。人間の貴重なレビュー時間を、機械が潰せる退屈な穴の指摘ではなく、本当に難しい設計判断に集中させること。ノイズを消し、確証だけを赤にするのは、まさにそのためです。

なお、ここで扱った「PRごとのスキャン」を超えて、継続的なCI認可チェック(チームのリポジトリに対する常時監視や、認可設計の継続的な検証)まで踏み込む領域は、提供準備中の上位プラン「Aegis Team」で扱う構想です。関心があれば先行登録(ウェイトリスト)から。現時点のOSS版(npx @aegiskit/cli scan)でも、本記事のCIゲートは今日から組めます。


11. CI導入チェックリスト

CIセキュリティゲートを「死なないゲート」として組むための最小確認項目です。

  • PRとpushの両方でスキャンが走る(on: [push, pull_request]
  • permissionscontents: read + security-events: write の最小権限
  • SARIFアップロードに if: always() を付け、赤でも指摘が必ず載る
  • 結果が コードスキャニングのSecurityタブPR差分の注釈に出ている
  • 段階1(warn)から開始し、ベースラインを片付けてから block に昇格
  • ブロックするのは confirmed(高確度・動的再現済み)だけ——ノイズは warning に留める
  • block 昇格後、ブランチ保護Security チェックをマージ必須に指定
  • CIから外部認証が要るなら OIDC(短命トークン)——長期キーをSecretsに置かない
  • Action参照は tomodahinata/aegis@main(必要ならコミットSHAでピン留め
  • RLSの退行を pgTAP回帰テストで同じCIに束ねている
  • CIが緑=安全ではないことをチームが理解している(設計レビューは別途)

発注者・チームリードの視点で最も効く問いは、**「セキュリティチェックはCIに入っていますか?」「赤が出たとき、それは"本当にヤバい"と信用されていますか?」**の2つです。後者に「いや、ノイズが多くて…」と返ってくるなら、ゲートは事実上死んでいます。


まとめ:仕組みで止め、確証だけを赤にする

要点を整理します。

  • セキュリティ検査はPRの時点でCIに入れて初めて意味を持つ。本番後に探すのではなく、マージ前に止める(シフトレフト)。価値の源泉は「人の規律」ではなく「構造での強制」。
  • SARIFは静的解析結果の標準フォーマット。これに統一すれば、GitHubコードスキャニングのSecurityタブと、PR差分の行単位注釈に結果が載り、ツールを乗り換えてもCI連携は不変。
  • GitHub Actionsでの実装は短い。permissions: security-events: write + contents: read の最小権限、if: always() でのSARIFアップロード、severity での閾値指定が骨格。Action参照は tomodahinata/aegis@main
  • CIゲートの最大の敵は誤検知。ノイズだらけのゲートは必ず迂回される。だから**「高確度のみブロック」——静的の疑いを動的プローブで再現できたもの(SAST×DAST相関)**だけを赤にする。
  • 導入はwarn から始め、確証だけを block に昇格。CIから外部認証が要るなら**OIDC(鍵レス)**で長期シークレットを排除。
  • 正直に言えば、CIゲートは設計レビュー・手動監査の代わりにはならない。ツールは認可の"正しさ"を証明しない。これは継続運用の"仕組み化"であり、人間の判断を補完するもの。

AIで速く作ること自体は正しい。速く作ったものを、漏らさず安全に固める仕組み——その第一歩として、まずはAegis(無料OSS、npx @aegiskit/cli scan)でCIゲートを組んでみてください。確証だけが赤になる体験を作れば、セキュリティは「気をつけるもの」から「構造で守られるもの」に変わります。

それでも、認可・RLSの設計そのものの正しさや、既存アプリの継続的な堅牢化が必要であれば、機械では塞げない領域です。私自身、サーバーレス決済プラットフォームでフルスタック開発と決済信頼性レイヤーを主導し、CI/CDと検証ゲートを実運用で設計してきました。どこまで自動化で固め、どこから人手のレビューが要るか——その線引きを含め、セキュリティ監査で承ります。


よくある質問(FAQ)

Q. まず何から始めればいいですか? A. 第4節のYAMLを .github/workflows/security.yml に置き、continue-on-error: true(段階1)で警告のみから始めてください。これでPRに指摘が出るようになります。ノイズの傾向が掴めたら continue-on-error を外し、ブランチ保護でマージ必須にします。

Q. SARIFは自分で書く必要がありますか? A. いいえ。SARIFはツールが自動生成します。あなたが書くのは upload-sarifsarif_file を渡すYAMLだけです。SARIFの構造を理解しておく価値はありますが、手書きはしません。

Q. なぜ全部の検出でブロックしないのですか? A. 第5節のとおり、誤検知でCIが頻繁に赤くなると、ゲートが信用されず必ず迂回されるからです。確証(高確度・動的再現済み)だけをブロックに限定し、残りは警告として可視化する——これがゲートを「生かす」唯一の現実的な設計です。

Q. CIが緑なら、もう安全ですか? A. いいえ。CIゲートが見ているのはコードとSQLの"形"であって、認可の"正しさ"ではありません。緑は「よくある罠は踏んでいない」を意味するだけです。事業ルールやテナント帰属の妥当性は、人間の設計レビューでしか判断できません。CIゲートは監査を補完するもので、置き換えるものではありません。

Q. 個人開発や小規模でもやるべきですか? A. むしろ小規模ほどコスパが高いです。YAMLは10数行、OSSなので費用ゼロ。continue-on-error で警告から始めれば、既存PRを止めずに導入できます。AIで素早く作ったアプリこそ、CIに番をさせる価値が大きいというのが実情です。


参考資料

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この記事の対策、ツールで自動化できます

Next.js / Supabase のセキュリティ統制を、OSS の Aegis で自動化

この記事の対策の多くは、ミドルウェア1枚と静的解析で機械的に検出・強化できます。無料・MIT の Aegis なら、いまのプロジェクトを1コマンドからスキャンできます。設計が要る「縦のリスク」は監査でも承ります。

プロジェクト単位(請負)・技術顧問のどちらにも対応可能です。まずは30分の無料技術相談から。