Scout Security について
Scoutは、コードや依存関係、Git履歴の一般的な問題を調べる、開発者向けのローカル静的セキュリティスキャナーです。APIキーやトークン不要の決定的なルールで動作し、CIやコミットフック、AI向け修正プロンプトに結果を活用できます。
主な機能
- 01漏えいシークレットとインジェクションの検出
- 02セキュリティヘッダーと脆弱な依存関係の確認
- 03taint解析とカスタムルール
- 04Markdown、JSON、SARIFレポートの生成
- 05ベースラインと深刻度によるCI制御
活用シーン
- 01コミット前のコード変更をスキャン
- 02CIで高深刻度の検出結果をブロック
- 03既存プロジェクトの検出結果をベースライン化
- 04Git履歴内の漏えいシークレットを検索
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Scout
CLI 内の AI セキュリティチームです。 ハッカーに見つかる前に脆弱性を発見しましょう — 無料、ローカルで動作し、登録も不要です。
Scout を選ぶ理由
AI コーディングアシスタントは、安全でないコードを絶えず生成します — ハードコードされたシークレット、SQL インジェクション、認証の欠如などです。セキュリティチームがいないため、個人開発者はそのままリリースしてしまいます。
Scout はそのチームです。 静的解析により、AI アシスタントがよく犯すミス — 漏えいしたキー、文字列連結で組み立てた SQL、shell=True、セキュリティヘッダーの欠如など — を検出します。API キーも設定も不要で、費用もかかりません。
インストール
インストール不要 — uv を使って、1 つのコマンドですぐに試せます(仮想環境不要、初回起動は約 1 秒です)。
uvx scout-security scan ./my-project
または、恒久的にインストールします。
pip install scout-security
NCC ScoutSuite も使っていますか? こちらも
scoutコマンドをインストールするため、最後にインストールしたパッケージがその名前を使用します。Scout はさらにscoutsecもインストールします — 同じツールを衝突しない名前で使えます:scoutsec scan ./my-project。
使い方
# Scan a project — deterministic static analysis: no API keys, no tokens, no signup
scout scan ./my-project
# Turn the findings into ready-to-paste fix prompts for your AI assistant
scout scan ./my-project --format ai-prompt
出力形式
1 回のスキャンで 4 種類の表示ができます — --format(-f)で選択してください。
# Layer 1 — human-readable Markdown report (default)
scout scan ./my-app
scout scan ./my-app -o security-report.md
# Layer 2 — ready-to-paste prompts for your own AI (Cursor, Claude, Copilot…)
scout scan ./my-app --format ai-prompt # writes security-prompts.md
scout scan ./my-app --format ai-prompt -o prompts.md
# Layer 3 — machine-readable JSON for piping into agentic tooling / CI
scout scan ./my-app --format json # prints JSON to stdout
scout scan ./my-app --format json -o report.json
scout scan ./my-app --format json | jq '.findings[]'
# Layer 4 — SARIF 2.1.0 for GitHub Code Scanning (PR annotations)
scout scan ./my-app --format sarif -o scout.sarif
どの形式でも同じエンジンが動作します — Scout が問題を見つけ、コードベースをすでに把握しているお手元の AI が修正を適用します。
CI のゲートとして使う
scout scan は、--fail-on(既定値:high)以上の重要度の検出結果がある場合に 1 で終了するため、実際の問題があればパイプラインが失敗します。
scout scan . --fail-on high # default — fail on HIGH or CRITICAL findings
scout scan . --fail-on critical # fail only on CRITICAL
scout scan . --fail-on never # report-only mode — always exit 0
GitHub Action はインストール、スキャン、SARIF のアップロードをまとめて行うため、GitHub Code Scanning 経由で検出結果が PR の注釈として表示されます。
jobs:
scout:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: Varpost/[email protected]
with:
fail-on: high # also: path, format, upload-sarif
通常のステップを使いたい場合は、同じ処理を手動で行えます(ジョブには引き続き security-events: write が必要です)。
- run: |
pip install scout-security
scout scan . --no-ai --format sarif -o scout.sarif --fail-on never
- uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: scout.sarif
Pre-commit フック
検出結果をコミットする前に見つけましょう。
# .pre-commit-config.yaml
repos:
- repo: https://github.com/Varpost/Scout
rev: v0.1.16 # use the latest tag
hooks:
- id: scout
このフックは、コミットのたびにリポジトリのルートから scout scan . --no-ai --fail-on high を実行するため、[tool.scout] の設定が適用されます。しきい値は args: ["--fail-on", "critical"] で調整できます。失敗すると、Scout は詳細を記載した security-report.md を出力します — .gitignore に追加しておくとよいでしょう。
検出結果の抑制
問題が報告された行の末尾にコメントを追加して、誤検出を抑制できます。
result = eval(trusted_expression) # scout: ignore
result = eval(trusted_expression) # scout: ignore[injection]
単独の scout: ignore は、その行にあるすべての検出結果を抑制します。対象を指定する形式では、名前付きスキャナー(secrets、injection、headers、deps、custom)または検出 ID(例:injection/eval_usage — --format json の id フィールド)だけを抑制します。インラインコメントを付けられない検出結果 — アプリ全体に対する CSRF チェックには意味のある行がなく、ロックファイルの検出結果は生成された JSON 内にあります — は、[tool.scout] の scanners(下記)でスキャナーを無効にするか、ベースラインに登録して(下記)対処します。
設定
--exclude でパスをスキップします(複数回指定可能。スキャンルートからの相対パスで、グロブも使用できます)。
scout scan . --exclude tests/fixtures --exclude "*.min.js"
または、pyproject.toml にプロジェクトの既定値を設定します — Scout はスキャン対象プロジェクトの [tool.scout] を読み込みます。
[tool.scout]
exclude = ["tests/fixtures", "vendor"] # paths or glob patterns to skip
scanners = ["secrets", "injection"] # run a subset: secrets, injection, headers, deps, custom
engines = ["semgrep"] # external engines to run and merge (optional)
rules = ["scout-rules.yml"] # your own YAML detection rules (optional)
fail_on = "medium" # default threshold for --fail-on
CLI フラグが優先されます。--exclude は設定のリストを置き換え、--engine は engines を置き換え、--fail-on は fail_on を上書きします。
カスタムルール(任意)
YAML ファイルを使って、プロジェクト固有のパターンを Scout に教えられます — ID、正規表現、メッセージ、重要度を指定します。
# scout-rules.yml — referenced from [tool.scout] rules
rules:
- id: internal-api-host
pattern: "internal\\.corp\\.example"
message: "Internal hostname committed to source."
severity: HIGH # CRITICAL | HIGH | MEDIUM | LOW
fix_phase: 1 # optional, 1-5 (default 3)
suffixes: [".py", ".ts"] # optional — default: every scanned file
fix: "Move the hostname to configuration."
ルールは意図的に、メタデータ付きの grep として設計されています — メタ変数や汚染解析が必要なら、--engine semgrep を使います。ルールが不正な場合は標準エラーに警告が出て、そのルールはスキップされます。スキャンが中断されることはありません。カスタム検出結果は、標準の検出結果と同じ機能をすべて利用できます:scout: ignore[custom]、ベースライン、重要度によるゲート、JSON/SARIF。
外部エンジン(任意)
Scout は業界標準の OSS エンジンをオーケストレーションし、その検出結果をレポート、JSON、SARIF 出力に統合できます。フェーズ別の修正計画はそのままに、対象範囲を拡大します。
pip install semgrep # or brew install semgrep
scout scan . --engine semgrep # native scanners + semgrep, merged & deduped
# CodeQL — GitHub's semantic analysis engine (CLI from
# https://github.com/github/codeql-cli-binaries, on PATH as `codeql`)
scout scan . --engine codeql # builds a CodeQL DB per language (python/js),
# runs the official security queries, merges the SARIF
--engine codeql を実行すると、GitHub のコードスキャンで使用されるものと同じクエリスイートが実行されるため、Scout のレポートに完全なセマンティック解析の検出結果を含められます。数秒ではなく、数分かかることを想定してください(データベースの抽出は CodeQL の設計によるもので、Scout のオーバーヘッドではありません)。
エンジンは明示的に指定した場合のみ使用されます。デフォルトのスキャンは引き続き依存関係ゼロで、完全に決定的です。指定されたエンジンがインストールされていない場合は、1 行のメッセージを表示してスキップします。クラッシュすることはありません。ネイティブスキャナーがすでに検出した行に該当するエンジンの検出結果は破棄され、Scout 独自の修正ガイダンスが優先されます。
VS Code 拡張機能
scout-vscode/ は CLI を VS Code 拡張機能としてラップします。Python/JS/TS ファイルを保存すると、そのファイルだけをスキャンし(1 秒未満)、検出結果をインラインの波線で表示します。汚染追跡された検出結果には、ユーザー入力から到達可能と表示されます。Scout: Scan Workspace コマンドを実行すると、プロジェクト全体の検出結果が Problems パネルに表示されます。scoutsec を呼び出すため、[tool.scout] の設定は変更せずに適用されます。
既存のコードベースへの Scout の導入(ベースライン)
CI ゲートを有効にする前に、何年分もの検出結果を修正したくない場合は、現在の状態を受け入れ、新しい検出結果だけを失敗扱いにできます。
scout scan . --write-baseline # accept current findings → .scout-baseline.json
scout scan . --baseline .scout-baseline.json # report and fail only on NEW findings
.scout-baseline.json をコミットしてください。検出結果の識別にはコンテンツベースの方式を採用しています。ルール、ファイル、フラグが立った行のハッシュで識別し、意図的に行番号は含めません。そのため、無関係な編集によってファイル内の位置が上下しても、ベースラインに記録された検出結果は引き続き受け入れられます。フラグが立った行自体を変更すると、その検出結果が再びレビュー対象になります。
Git 履歴のシークレットをスキャンする
コミット後に削除されたシークレットも、漏えいした事実は変わりません。現在のコードをスキャンしても見つけられません。
scout scan . --git-history # secrets in every added line of every commit, all branches
検出結果は、それが導入されたコミットに紐づけられます(config.py @ 1a2b3c4d5e6f)。報告されたものはすべてローテーションしてください。行を削除しても、認証情報の漏えいは取り消せません。PATH 上に git が必要です。作業ツリーではなく履歴をスキャンします。
対象範囲について正直に言うと、Gitleaks と TruffleHog は、履歴の詳細かつ高速な監査を主な目的としています。Scout のスキャンは組み込みの利便機能であり、これらに代わるものではありません。
検出対象
| スキャナー | 検出対象 | 重大度 |
|---|---|---|
secrets | AWS/Google のキー、GitHub/GitLab のトークン、Anthropic と OpenAI のキー、Slack/npm/PyPI のトークン、Stripe のキー、DB URL、秘密鍵、パスワード | CRITICAL |
injection | SQL インジェクション、NoSQL 演算子インジェクション、コマンドインジェクション、eval()/Function/vm、XSS | CRITICAL |
injection(汚染追跡による判定) | パストラバーサル(ファイルの読み書き、sendFile)、SSRF(fetch/requests/axios)、安全でないデシリアライズ(pickle/yaml.load/unserialize)、オープンリダイレクト(redirect(...))。ユーザー入力がシンクに到達した場合のみ検出 | HIGH |
injection(キーワードによる判定) | トークン/シークレットに使用される脆弱な乱数生成(トークン/パスワード/OTP に Math.random/random.* を使用) | MEDIUM |
headers | セキュリティヘッダーの欠如(Express/Flask/Django/FastAPI)、ワイルドカード CORS、CSRF 対策の欠如 | LOW–MEDIUM |
deps | pip と npm の依存関係における既知の脆弱性(OSV.dev 経由) | HIGH |
対象言語
詳細分析では、インジェクション(SQL/コマンド/XSS)とセキュリティヘッダーの検出対象を、検出パターンが慣用表現に依存するPython と JS/TSに限定しています。どちらの言語でもファイル内の汚染追跡を行います(Python では標準ライブラリの AST、JS/TS では字句解析パスを使用)。検出結果には、シンクからユーザー入力(request.*、req.body、location.hash など)まで追跡できた場合に reachable 判定が付与されます。ORM/NoSQL のシンクは汚染の証拠がある場合のみ検出され、証明可能なファイル内定数を受け取る XSS シンクは報告されずに除外されます。同じ汚染追跡エンジンで、パストラバーサル(open/fs.readFile/sendFile)、SSRF(requests/fetch/axios)、安全でないデシリアライズ(pickle/yaml.load/unserialize)、オープンリダイレクト(redirect(...))も検出します。いずれも到達可能性を条件とするため、open("config.json") や axios.get("https://api.example.com") は検出されません。トークン/シークレットの脆弱な乱数生成(Math.random/random.*)は、代わりにキーワードを条件とします。トークン/パスワード/OTP という名前と併せて使用されている場合のみ検出されます。シークレット検出は言語に依存しません。Scout が収集する一般的なすべてのソースファイルと設定ファイル(Go、Java、Ruby、PHP、C/C++、Rust、シェル、.env、Dockerfile、docker-compose、Terraform など)を対象に実行されるため、どの言語から漏えいしたハードコードキーでも検出できます。依存関係のスキャンでは、requirements.txt と package-lock.json が対象です。
測定された精度
Scout のインジェクションスキャナーは、OpenSSF CVE Benchmark の実際の CVE 104 件を対象に評価されています。実在する JS/TS プロジェクトの脆弱なコミットを使用し、合成テストケースは使っていません。詳細な手法、注意事項、再現手順は benchmarks/ にあります。結果はリリースごとにバージョン管理され、この README では、コミット済みの結果ファイルに記載された数値のみを引用しています。
v0.1.16 の結果を正直に読み解くと、全体の再現率は 27.4%、適合率は 3.2% です。どちらもリリースごとに向上しています(v0.1.9 では 16.5%/1.3%)。特に優れているのはコマンドインジェクションで、再現率は 41.7% となり、このコーパスにおける CodeQL の公表値 40% をわずかに上回りました。これは child_process.exec(cmd, callback) のメンバー呼び出しを認識できるようになったためです。[a, b].join(' ') で構築されたコマンドも対象です(v0.1.16 で正規表現の正確性を修正し、regexp.exec() の誤検知も抑制したため、再現率と適合率がともに向上しました)。SQL/NoSQL インジェクションは、JS の taint パスにより 25% を維持しており、CodeQL と同水準です。圧縮・バンドル済みファイルをスキップすることも、適合率の向上に寄与しています。生成されたバンドル内の脆弱性は、依存関係スキャナーが検出すべきものです。--engine semgrepを追加すると、全体の再現率はさらに上がります([semgrep の結果](benchmarks/results/0.1.16/summary-native-semgrep.md)を参照)。偽陽性の件数は、ベンチマークの慣例上、上限値です。ラベルの付いていない実際のexec()`/シンク呼び出しは、すべて Scout の誤検知として数えられます。これらの数値を公表するのは、公正な比較を促し、リリースごとに改善していくためであり、誇示するためではありません。同じコーパスにおける CodeQL、ESLint、および公表済みの研究との比較については、benchmarks/COMPARISON.md を参照してください。
パストラバーサル+SSRF(v0.1.12)およびデシリアライゼーション+オープンリダイレクト+弱い乱数(v0.1.13)の検出器は、新たな脆弱性 クラス(CWE-22/918/502/601/330)です。これらによって、上記のインジェクションの数値は変わっていません(TP/FP/FN が同一であることを確認済みです)。これらのクラスは、追加された 39 件の CVE に対して個別に評価されています。パストラバーサルの再現率は、2 つの原則に基づく対象範囲の拡大により、0% のベースライン(v0.1.13)から 46.9%(v0.1.14)に向上し、このクラスでは semgrep のパスさえ上回りました。リクエスト URL/パス(req.url)を taint ソースに加え、fs.stat/access/exists をファイルパスのシンクに加えています。SSRF、オープンリダイレクト、デシリアライゼーションは、誠実に 0% のままです。CVE のフローを調べると、障害となっているのは、認識されていないシンク/ソース(res.setHeader('Location', …) によるリダイレクトや、単独の request({uri}) クライアント)と、オブジェクトリテラルを介した taint であり、関数境界ではありません。この広がりを伴う変更で 11 件の CVE の残りを追うと、得られる効果以上に偽陽性が増えるおそれがあります。benchmarks/COMPARISON.md を参照してください。
v0.1.15 では、Python のファイル内クロス関数 taint 追跡を追加しました。ローカルヘルパーに渡された tainted 引数は、そのヘルパーのパラメーターも taint します。そのため、request.args の値がルートハンドラーを経由してサービス関数内の os.system に流れる場合、シンクまで追跡できます。これは、JS のみを対象とする OpenSSF コーパスでは測定できない、階層構造を持つ Python アプリでの実用的な改善です。弱い乱数と同様に、ベンチマークの数値ではなくユニットテストによって検証されています。
出力例
$ scout scan ./my-app
Scout v0.1.16 scanning: ./my-app
Scanning 47 files...
Found 6 issues:
🔴 2 critical
🟠 3 high
🟡 1 medium
Report written to: ./my-app/security-report.md
レポートには、次の内容が含まれます。
- すべての脆弱性についての平易な説明
- 深刻度の評価とその背景(危険な理由)
- 各問題に対する具体的な修正手順
- 段階的な修正計画(リスクゼロの修正を最初に実施)
オプション:AI による確認パス
コアスキャンは常に静的かつ決定論的で、オフラインで実行され、トークンを消費しません。同じスキャンでは同じ検出結果が得られ、API キーも不要です。 これがデフォルトであり、変更されることはありません。
誤検知をさらに絞り込みたい場合、Scout はオプションで、ヒューリスティックによる各検出結果について、フラグが付いた箇所のスニペットのみ(ファイル全体ではありません)を AI プロバイダーに送信できます。AI プロバイダーは重大度を引き下げるか、誤検知として除外できます。依存関係(OSV)およびプロジェクトレベルの検出結果は決定論的な事実であり、再判定されることはありません。プロバイダーでエラーが発生しても、検出結果はそのまま維持されます。このパスはフェイルオープンのため、実際の問題が隠されることはありません。
デフォルトではオフです。実行ごとに有効にします:
# Anthropic (needs ANTHROPIC_API_KEY) — uses the cheap Haiku tier by default
scout scan . --model anthropic
# OpenAI (needs OPENAI_API_KEY)
scout scan . --model openai
# Local Ollama (no key, no cloud) — nothing leaves your machine
scout scan . --model ollama --ollama-model llama3
プロバイダーの解決順序は --model > SCOUT_AI_PROVIDER 環境変数 > none です。プロバイダーごとにモデルを上書きするには、SCOUT_AI_MODEL を使用します。--no-ai を指定すると、設定にかかわらずこのパスはオフになります。SDK を pip install "scout-security[ai]" でインストールしてください(Ollama には追加のインストールは不要です)。
MCP サーバー(エージェントの検証ツール)
Scout を MCP ツールとして実行すると、コーディングエージェントがスキャン → 修正 → 再スキャンのループで呼び出せます。決定論的で、オフラインで実行され、トークンを消費せず、推論コストもかかりません。Scout が検出し、エージェントが修正し、Scout が再検証します。
(GitHub は cursor:// のディープリンクを削除するため、Cursor のバッジからはサイトのワンクリックボタンに移動します。)
Claude Code プラグインとしてインストール
ワンコマンドでインストールできます。プラグインに MCP サーバーが含まれているため、個別に claude mcp add を実行する必要はありません:
/plugin marketplace add Varpost/Scout
/plugin install scout@scout
これにより、scan_path ツールと /scout-scan [path] コマンドが登録されます。PATH 上に uv が必要です。プラグインは uvx でサーバーを起動します(初回実行時にパッケージがダウンロードされ、以降の実行ではキャッシュが使われます)。uv がない場合は、以下の手動セットアップで pip install "scout-security[mcp]" を実行し、代わりに "command": "scout-mcp" を使用してください。
手動セットアップ(任意の MCP ホスト)
どの MCP ホストでも、同じサーバー定義を使用します。uv を使えば、インストールは不要です:
{
"mcpServers": {
"scout": {
"command": "uvx",
"args": ["--from", "scout-security[mcp]", "scout-mcp"]
}
}
}
uv がない場合は、pip install "scout-security[mcp]" を実行し、args を指定せずに "command": "scout-mcp" を使用してください。
この定義を配置する場所:
| ホスト | 場所 |
|---|---|
| Claude Code | 上記のプラグイン、または claude mcp add scout -- uvx --from "scout-security[mcp]" scout-mcp |
| Cursor | プロジェクト内の .cursor/mcp.json、または全プロジェクト共通の ~/.cursor/mcp.json |
| Claude Desktop | claude_desktop_config.json(設定 → 開発者 → 設定を編集) |
| Cline | cline_mcp_settings.json(MCP サーバー → MCP サーバーを設定) |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
| VS Code(ネイティブ MCP) | .vscode/mcp.json — 同じサーバーオブジェクトを "mcpServers" ではなく "servers" キーの下に配置します |
公開されるツールは scan_path(path) の 1 つです。--format json と同じ Layer-3 JSON(ファイル、行、重大度、安定した ID、説明、修正方法を含む検出結果)を返します。エージェントの修正ループからこのツールを呼び出し、問題が解消されたことを確認するために再度呼び出してください。
Scout を AI アシスタントと使う
要点は一文です:Scout が決定論的に検出 → AI が修正 → Scout が再検証。 毎回同じスキャンで同じ検出結果が得られ、トークンはゼロです。そのため、修正の再確認にも推論コストはかかりません。作業方法に合ったインターフェースを選んでください。3 つとも同じエンジンで実行されます。
1. あなた+チャットアシスタント(Claude、Cursor、Copilot Chat)
scout scan . --format ai-prompt # writes security-prompts.md
security-prompts.md を開き、ブロックをアシスタントに貼り付けます。それぞれ単体で使えます。指摘事項と修正方法に加え、同じ種類の問題がほかのコードにもないか調べるよう指示します。編集が終わったら、再検証します。
scout scan . # clean? the loop is closed
2. Scout 自体を呼び出すエージェント(Claude Code、Cursor Agent)
MCP サーバーを接続してから、エージェントに次のループを指示します。
Scout でこのプロジェクトをスキャンし、すべての指摘事項を修正してから、もう一度スキャンしてください。指摘事項がゼロになるまで繰り返してください。
エージェントは scan_path を呼び出して修正を適用し、再度呼び出します。Scout はループ内の決定論的なゼロトークン検証ツールなので、再チェックは無料です。
3. CI/pre-commit(ループを必須にする)
ループをゲートとして設定し、指摘事項が修正されるまでビルドを失敗させます。
scout scan . --fail-on high # exit 1 on HIGH+ findings
GitHub Action についてはCI ゲートとして使用するを、コミット前に指摘事項を検出する方法についてはPre-commit Hookを参照してください。既存のリポジトリに導入する場合は、ベースラインを使うと、現在の指摘事項は許容し、新しい指摘事項があった場合のみ失敗します。
カスタムスキャナーを追加する
from scout.scanners import register_scanner
from scout.scanners.base import BaseScanner
from scout.models import Finding
from pathlib import Path
@register_scanner
class MyScanner(BaseScanner):
name = "my-scanner"
description = "Detects my custom pattern"
def scan_file(self, file_path: Path, content: str) -> list[Finding]:
findings = []
# detection logic here
return findings
scout/scanners/__init__.py に import を1つ追加すれば完了です。
開発
git clone https://github.com/Varpost/Scout.git
cd Scout
pip install -e ".[dev,ai]"
pytest
ruff check scout/ tests/
ドキュメント
ドキュメントとインタラクティブガイドの全文はこちらです:https://varpost.github.io/Scout/
ライセンス
MIT — いつまでも無料です。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。