mcpField
O
orca-sec-scans

orca-sec-scans

github.com/rheinmirセキュリティ10256 回インストール2 週間前に更新
リポジトリ

orca-sec-scans について

orca-sec-scans は、開発者や CI 向けの読み取り専用セキュリティスキャンスキルです。Trivy による静的検査に実リクエストでの検証と任意の類似ドメイン監視を組み合わせ、静的検査だけで安全と判断しない構成です。

主な機能

  1. 01依存関係の CVE、設定不備、ファイル内の秘密情報を検査
  2. 02JSON と HTML のレポートを生成
  3. 03実際の HTTP・DNS リクエストで前提を検証
  4. 04修正後に再スキャン
  5. 05任意で類似ドメインと証明書を確認

活用シーン

  1. 01リリースやデプロイ用ブランチのマージ前に検査
  2. 02CI でリポジトリを定期スキャン
  3. 03API 認証とドメイン公開状態を検証
  4. 04ブランド類似ドメインと証明書を調査

インストール

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

$npx skills add https://github.com/rheinmir/setup --skill orca-sec-scans

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

詳細

スキル:orca-sec-scans

概要

目的とコンテキスト
  • 目的: ローカルでもCI/Jenkinsでも使える、静的な読み取り専用のセキュリティスキャンフローです(スキャン中にTrivyがコードを変更することはありません)。対象は、依存関係のCVE(Go/Node/Pythonのロックファイル)、設定ミス(Dockerfile/compose/nginx)、ファイル内に露出したシークレットです。 この静的スキャンに加えて、開発者のデフォルトの想定を実際のリクエストで検証する動的スキャンと、外部に対するスキャン(サプライチェーン/ブランド、keyless)の2つのレイヤーがあります。
  • トリガー(使用するタイミング):
    • ユーザーが「セキュリティスキャン」「スキャン」「trivy」「CVEをチェック」「security scan」「脆弱性があるか」と言った場合
    • リリース前/デプロイ用ブランチへのマージ前
    • CIで定期的に実行する場合(trivy fs . --config trivy.yaml --exit-code 1)
    • DiffがTrigger-conditionsの表(認証、ユーザー入力、シークレット、新しいエンドポイント、決済/機密データ、アプリのパブリックドメインへの公開)に該当する場合 → スキャンは必須です。ユーザーが「脆弱性があるか」「安全か」と言った場合 → 常にトリガーになります。
  • 対象外: サブモジュールに未コミットの変更がある場合に一括で自動更新すること、レポートから検出結果を削除すること(受け入れる場合は.trivyignoreに記録します)、レポートをデプロイ先サーバーにコミットすること、cti-expertのような広範な脅威調査(supply-watch keylessの範囲に限ります)。
メンタルモデル

Trivyはあるか? → 対象範囲(ロックファイル)→ HIGH/CRITICALの静的スキャン → JSON+HTMLレポート → 要約+修正案 → 再スキャンでNONE、並行して開発者の想定 → 実際のリクエスト(curl/dig/git diff)→ 検証または脆弱性の確認を行い、必要に応じてブランド名 → 決定的なバリエーション → 稼働中のDNS+CTログを実行します。静的スキャンに問題がなくても、安全とは限りません。

入力と出力の契約
項目必須?意味
入力ソースコードディレクトリ(be、feまたは.)はいスキャン対象。リポジトリにtrivy.yamlがあれば使用します
入力HOST/稼働中のドメイン動的スキャンでは必須curl/digで実際の状態を検証します
入力ブランド名いいえsupply-watch.pyで使用します
出力security/trivy-report.json + security/trivy-report.htmlはい完全なレポート。レビュー用アーティファクトです
出力対象ごとのHIGH/CRITICAL一覧+修正案はい依存関係の更新、USERの非root化、シークレットのローテーション
出力動的スキャン結果はい各想定の正誤を、コマンド+実際のHTTP/DNSコードとともに示します
出力再スキャン結果修正がある場合remaining = NONE
出力supply-watchレポート任意rc 0は問題なし、2は検出あり。crt.shのエラー時は → スキップ
ルールと機能
  • RULE-01(必須):静的スキャン(Trivy)と動的スキャン(上記チェックリスト)は異なる2つのレイヤーです。両方を実行してください。 TrivyはCVE/設定ミス/ファイル内のシークレットを検出しますが、認証バイパス、パブリック公開、CORS/CSRFのロジック、ブランチの不一致は検出しません。Trivyレポートに問題がないことを、安全の根拠と見なさないでください。
  • RULE-02(必須):開発者のデフォルトの想定を信用しないでください。「ログイン機能がある」「内部向けなので安全」「動作している」といった主張は、結論を出す前に必ず実際のリクエストで検証してください。
  • RULE-03(必須):スキャン中、Trivyはコードを変更しません。いつでも安全に実行できます。
  • RULE-04(必須):レビュー済みで受け入れた検出結果は、.trivyignoreに記録してください(1行につきID 1つ+理由のコメント+日付)。レポートから削除してはいけません。
  • RULE-05(必須):security/*.json|htmlをデプロイ先サーバーにコミットしないでください。レビュー用アーティファクトに限ります。
  • RULE-06(必須):bonbon-aiのデプロイ時は、サーバーにプッシュするのはbeとfe(2つのサブモジュール)のみです。ツール類(trivy.yaml、security/、スキル)はサーバーに配置しません。
  • RULE-07(必須):修正の変更はすべて、コミット前にビルド/検証を行ってください(go build ./...、pnpm iなど)。
  • 機能:不足している場合はローカルにスキャンツールをインストールすること、ソースコードを読み取り専用で静的スキャンすること、プロジェクト自身のホストに実際のHTTP/DNSリクエストを送ること、修正適用が許可されている場合にマニフェスト/Dockerfileを変更すること、公開CTログ/DNS(keyless)を参照すること。
失敗時の境界
  • Trivyをインストールできない → ブロック。ユーザーに報告してください。
  • サブモジュールに未コミットの変更がある → 修正を提案するだけにとどめ、自動更新は行いません。
  • 修正後にビルドできない(go build ./...、pnpm i)→ 失敗。コミットしません。
  • 動的スキャン用のHOSTがない → 一部のみ完了。静的スキャンのみを実施し、動的スキャンのレイヤーを実行していないことを明示します。「安全」と結論付けてはいけません。
  • シークレットが検出された場合 → 直ちにキーをローテーションしてください(ファイルから削除するだけでは不十分です)。
  • supply-watchからcrt.shにアクセスできない → スキップし、問題なしとは判断しません。

手順

ワークフローの概要
手順種別入力アクション出力/終了条件失敗時/次の手順
W01効果マシン手順 0 — Trivy の確認とインストール(必ず最初に実行)trivy --version の出力インストール失敗 → ブロック
W02決定的リポジトリ手順 1 — ロックファイルから言語を検出し、ビルド/ベンダーディレクトリを除外スコープ—
W03決定的スコープ手順 2 — 脆弱性、設定ミス、シークレットをスキャンし、HIGH/CRITICAL を優先検出結果—
W04決定的検出結果手順 3 — JSON + HTML レポートを security/ に出力レポート 2 ファイル—
W05判断検出結果手順 4 — HIGH/CRITICAL をターゲットごとに要約し、修正を提案表 + 提案サブモジュールに未コミットの変更がある場合 → 提案のみ
W06決定的修正済みターゲット手順 5 — 再スキャンして確認remaining = NONE残存 → W05 に戻る
W07効果HOST、差分動的スキャン:実際のリクエストを使って、開発環境で想定される 8 つのケースをチェック各ケースに証拠ありHOST なし → 一部のみ
W08決定的ブランド名supply-watch.py(B03)で外部スキャンrc 0 または 2crt.sh エラー → スキップ

各手順の詳細(W01〜W08 の唯一の情報源):

ワークフロー
手順 0 — Trivy の確認とインストール(必ず最初に実行)
if ! command -v trivy >/dev/null 2>&1; then
  echo "Trivy chưa có → cài…"
  if [[ "$(uname)" == "Darwin" ]]; then
    brew install trivy
  else
    # Linux: dùng script chính thức Aqua (không cần root nếu set BINDIR)
    curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
      | sh -s -- -b /usr/local/bin
  fi
fi
trivy --version   # xác nhận; DB vuln tự cập nhật lần chạy đầu
手順 1 — 言語の検出(スキャン範囲)

ロックファイルを探してエコシステムを特定します:go.sum/go.mod(Go)、package-lock.json/pnpm-lock.yaml(Node)、requirements.txt/poetry.lock(Python)。node_modules、.next、.contentlayer、_archives、.git は除外します。

手順 2 — スキャン(迅速化のため HIGH+CRITICAL を優先)
trivy fs <dir> \
  --scanners vuln,misconfig,secret \
  --severity HIGH,CRITICAL \
  --skip-dirs '**/node_modules' --skip-dirs '**/.next' \
  --skip-dirs '**/.contentlayer' --skip-dirs '_archives' \
  --no-progress

bonbon-ai リポジトリでは、be と fe を個別にスキャンします(それぞれがサブモジュールです)。リポジトリに trivy.yaml がある場合は、--config trivy.yaml を優先します。

手順 3 — 完全なレポートの出力
mkdir -p security
TPL=$(find $(brew --prefix trivy 2>/dev/null || echo /opt/homebrew) -name html.tpl 2>/dev/null | head -1)
trivy fs . <cờ skip-dirs như trên> --no-progress -f json     -o security/trivy-report.json
trivy fs . <cờ skip-dirs như trên> --no-progress -f template --template "@$TPL" -o security/trivy-report.html
手順 4 — 要約と修正の提案

ターゲットごとに HIGH/CRITICAL の件数を数えて表に出力します。その後、修正を提案します(サブモジュールに未コミットの変更がある場合は、依存関係を一括で自動更新しないでください)。

  • 簡単な依存関係の更新(直接依存関係で、マニフェストを直接変更):例:requirements.txt の python-multipart。
  • 間接依存関係:go get <pkg>@<ver> を実行し、go build ./... で検証します。go get によって go ディレクティブが引き上げられる場合があります。Dockerfile のベースイメージを超える場合は、バージョンが合うように FROM golang:X-alpine も更新します。
  • 設定ミス DS-0002(root ユーザー):Dockerfile に非 root の USER を追加します(alpine では adduser -D、debian では useradd -m、node-alpine イメージでは USER node を使用します。volume/data などの書き込み先ディレクトリの chown も忘れないでください)。
  • シークレット:Trivy が検出した場合は、ファイルから削除するだけでなく、直ちにキーをローテーションします。
手順 5 — 再スキャンして確認

修正済みターゲットに対して手順 2 を再実行し、remaining = NONE を確認します。

外部スキャン — サプライチェーンとブランド(第 3 の軸、キー不要)

上記の 2 つは、どちらもプロジェクトの内部を確認します。外部を確認するものはありません。ユーザーをだますために、誰かがあなたの名前に似たドメインやパッケージを取得していないか、あるいはあなた自身のインストールコマンドに偽の依存関係を挿入していないかを調べます。

python3 fdk/tools/supply-watch.py <tên-thương-hiệu>            # sweep mặc định 7 TLD
python3 fdk/tools/supply-watch.py <tên> --tld com,dev --json   # cho CI
python3 fdk/tools/supply-watch.py --self-test

6 種類のパターン(文字の削除、文字の重複、文字の入れ替え、隣接キーの打ち間違い(QWERTY キーボード)、見た目が似た文字(o→0、l→1)、ハイフンの追加)で決定的かつオフラインでバリアントを生成し、DNS に問い合わせて稼働中のものを確認します。さらに、CT モニターが Certificate Transparency(crt.sh)を調べ、似たドメインに新たに発行された証明書がないかを確認します。

API キーは不要で、.venv も不要です。終了コード:0 は問題なし、2 は検出あり。crt.sh に接続できない場合は、問題なしと判定せず、スキップと表示します。

7onez/cti-expert(ワークフロー 08)から必要最小限の機能を取り入れています。意図的にこの部分だけを採用しています。cti-expert は、外部の脅威を調査するための 121 個の op と 78 個の MCP ツールを備え、.venv、API キー、アウトバウンドネットワークを必要とします。全体をそのまま統合すると、キー不要でオフライン実行可能なゲートに、キーやネットワークへの依存を持ち込むことになります。

動的スキャン — 開発者の思い込みを検証(Trivy を補完)

原則:Trivy(静的解析)ではアーキテクチャ/ロジック/実行時設定の不具合は検出できません。 最も深刻な脆弱性は、多くの場合、開発者の既定の思い込みに潜んでいます。実際のリクエストで検証する必要があり、言葉を信じてはいけません。「動く」≠「安全」です。

2026/06/22 のインシデントからの教訓:給与 ETL API に認証がなく(認証は Web 層にしかなく、/etl パスは nginx 経由で迂回可能)、誰でも curl で従業員 3,637 人の給与と PII を取得できました。「社内向け」のつもりでしたが、パブリックドメイン devtingting.coteccons.vn(パブリック IP)があり、インターネット全体に接続できる状態でした。Trivy では検出できず、実際に curl/dig して初めて判明しました。

「信じないこと――必ず検証する」チェックリスト(開発者の思い込み → 実態 → 検証方法)
  1. 「リバースプロキシの背後にある API は、Web/UI にログイン機能があるので保護されている。」 → 誤り:認証は多くの場合 Web 層にしかありません。プロキシのパス(/etl、/api など)はブラウザーから直接呼び出せるため、ログインを迂回します。 → 検証:各 API ルートに直接、Cookie/トークンを付けずに curl を実行します。401 が返る必要があります。200+データが返る場合は脆弱性です。認証は API/プロキシ層(例:nginx の auth_request)に必要であり、UI だけでは不十分です。

    for p in data/stats/all report/export sync/status; do
      curl -k -o /dev/null -w "$p -> %{http_code}\n" https://HOST/etl/$p; done   # mong đợi 401
    
  2. 「社内サーバー/プライベート IP(192.168.x)なので、外部からアクセスできない。」 → 誤り:パブリックドメイン、tailscale funnel、ポートフォワーディングなどを経由して接続できる場合があります。 → 検証:dig +short <考えられるすべてのサブドメイン> を実行し、パブリック IP がないか確認します。外部ネットワークから curl を試します。「社内向け」を信じず、実際の DNS を確認してください。

  3. 「CORS を開放するのは脆弱性/CORS を閉じれば十分安全。」 → 認識違いです:CORS がブロックするのは、クロスオリジンでのブラウザーによる読み取りだけです。curl/スクリプトはブロックしません。書き込み CSRF も防げません(POST のクエリパラメーター/ボディなしのリクエストは simple request であり、プリフライトなしにサーバーが実行します。CORS は関係ありません)。実際の問題は多くの場合、認証なし+ポート開放です。正面の入口(認証)を閉じる前に、CORS に手間をかけないでください。

  4. 「デフォルト設定をそのままにしても問題ない。」 → デフォルト値の変数が本番環境に残っていないか確認してください:CORS_ORIGINS に localhost:3000 が残っていないか。シークレット/フラグにサンプル値が残っていないか。BIND_HOST が誤って 0.0.0.0 になっていないか。

    curl -k -D- -o /dev/null -H "Origin: http://localhost:3000" https://HOST/etl/health | grep -i access-control
    
  5. 「どのブランチをデプロイしても同じ。」 → 誤り:CI(Jenkins)がブランチ X を clone する一方で、サーバーではブランチ Y が実行されているなど、差異が生じることがあります。マージコンフリクトによってブロック全体が落ちる場合があります(例:compose の networks: がなくなり、undefined network となってデプロイに失敗)。 → 検証:CI が clone するブランチと実行中のブランチは同じですか? git diff <ci-branch> <running-branch> -- docker-compose.yml .env* deploy/ を実行します。

  6. 「paramiko/SSH で接続できれば完了。」 → Transport(...)/AutoAddPolicy はホストキーを検証しないため、MITM 攻撃でパスワードやファイルが盗まれる可能性があります。検証:known_hosts をピン留めし、RejectPolicy を使ってください。

  7. 「トークン/シークレットはどんな方法で渡してもよい。」 → URL の ?token= にトークンを入れると、nginx/uvicorn のアクセスログ、Referer、閲覧履歴に残ります。検証:シークレットはヘッダー/Cookieで渡し、クエリー文字列には含めないでください。

  8. 「SELECT * のほうが便利。」 → PII(CCCD/MST/BHXH/給与)を含むすべてのカラムが返されます。また、全カラムを対象とした search は値を探るオラクルになります。検証:返すカラムをホワイトリストで指定し、機密カラムを検索対象に含めないでください。

トリガー条件 — 必ずスキャンする必要があるコード変更

誰かがスキルの呼び出しを覚えるのを待つ必要はありません。diff が表の条件に当てはまった時点で、スキャンが必須になります(WorldFlowAI/everything-claude-code の security-review から抽出):

変更内容必須の対応理由
認証、セッション、権限管理の追加・変更Trivy + 動的スキャントークンを localStorage に保存すると XSS の影響を受けます。また、機密性の高い操作の前にロールチェックが欠けていると、Trivy では検出できない認可の不備につながります。
ユーザー入力の受け付け(フォーム、パラメーター、アップロード)Trivy + 動的スキャンスキーマによる入力検証がない場合や、ファイルアップロードのサイズ/タイプ/拡張子に制限がない場合、SQLi/XSS/RCE の侵入口になります。
シークレット/認証情報/API キーの扱いTrivy(シークレットスキャン)ソースコードへのキーのハードコードや、git 履歴への混入を防ぐ必要があります。キーは環境変数とプラットフォームのシークレットに保存し、.env は gitignore に含める必要があります。
新しい API エンドポイントの公開Trivy + 動的スキャン新しいエンドポイントには通常、レート制限 + CSRF 対策 + 権限チェックが欠けています。また、エラーメッセージから内部情報やスタックトレースが漏れるおそれがあります。
決済/機密データTrivy + 動的スキャン + 手動レビューPII/金銭に関する情報をログに記録してはいけません。エラーは汎用的なものにする必要があります。脆弱性が1つあるだけでプラットフォーム全体が侵害されるおそれがあるため、慎重に判断してください。
アプリをパブリックドメインに公開/リバースプロキシを変更動的スキャンその時点で、「内部」向けの認証なしの脆弱性がインターネットに公開されます(上記の開発環境を前提とするチェックリストを参照)。

表に該当しない場合は、リリースのタイミングでスキャンすれば十分です。自問する文言は、「この diff は上記6項目のいずれかに該当するか?」 です。1分以内に答えられます。ユーザーが「脆弱性はないか」「安全か」と尋ねた場合は、常にトリガーとなります。

分岐
ID種類条件動作スキップ/失敗再合流
B01conditional_requiredrepo bonbon-aibe と fe を個別にスキャンする(それぞれ submodule)。デプロイ時はその2つの submodule のみを push する別の repo の場合 → . をスキャンW04
B02conditional_requiredrepo に trivy.yaml がある--config trivy.yaml を優先するない場合 → デフォルトの skip-dirs フラグW04
B03user_optionalユーザーがサプライチェーン/ブランドの調査を希望supply-watch.py <名前> で7つの TLD と CT モニターをスイープする要求がない場合 → スキップ終了
B04conditional_required検出結果をレビューし、受け入れた.trivyignore に記録する(1行に1 ID + 理由 + 日付)。レポートからは削除しない—W06
B05conditional_requiredTrivy がシークレットを検出ファイルから削除するだけでなく、直ちにキーをローテーションする—W06
検証と停止条件

必須事項:Trivy の終了コード/出力(再スキャンして remaining = NONE)、curl の実際の HTTP ステータスコード(トークンなしの API ルートは 401 であること)、実際の dig 結果、branch の git diff、supply-watch.py の終了コード。ビルド/検証が成功してから修正をコミットします。人による判断が必要な事項:検出結果を .trivyignore に追加することの承認、決済/機密データを扱うフローの手動レビュー。再スキャンで問題がなく、チェックリスト内のすべての前提に証拠がある時点で停止します。Trivy だけを根拠に「安全」と結論づけてはいけません。

例
  • 該当例: 「repo bonbon-ai をセキュリティスキャンして」→ Trivy は導入済み → be、fe を個別にスキャン → HIGH が2件:requirements.txt 内の python-multipart + DS-0002 root user → 依存関係を更新 + USER node を追加 → ビルド成功 → 再スキャンで remaining = NONE;動的スキャンで curl /etl/data/stats/all をトークンなしで実行し 401 を確認。
  • 境界条件/失敗例: Trivy では問題がなくても、/etl/report/export に cookie なしで直接 curl すると 200 が返り、給与データが取得できる → 認証バイパスの脆弱性。静的スキャンのレポートに問題がなくても、重大な問題として報告する(RULE-01);dig +short でサブドメインからパブリック IP が返る → 「内部向け」という前提は誤りです。
  • 境界条件: crt.sh が応答しないときに supply-watch.py acme を実行 → CT モニターは「スキップ」と出力し、問題なしとは報告しない。

起源

  • 2026-07-17 吸収(adapt_mode: dissolve, T-260717-02): トリガー条件の表は、WorldFlowAI/everything-claude-code の skills/security-review/SKILL.md(When to Activate + 10項目のチェックリスト)から抽出しました。scratchpad/ に depth-1 で clone し、バイト列は vendor していません。

コメント