Keyspoor について
Keyspoorは、AIコーディングワークフロー向けのオフラインシークレットスキャナーです。CLI、Rustライブラリ、読み取り専用MCPサーバーを備え、ファイルやGitデータを調べても、値やソース断片をレポートに含めません。
主な機能
- 01ファイルとGitデータのオフラインスキャン
- 02ステージ済み変更とローカル履歴の検査
- 03ZIP、tar、gzipアーカイブの読み込み
- 04秘匿化したJSON、JSONL、SARIFレポート
- 05カスタムルールとフィンガープリントベースライン
活用シーン
- 01リポジトリ内の認証情報漏えいの確認
- 02コミット前のステージ済み変更の検査
- 03ローカルで参照できるGit履歴の確認
- 04コーディングエージェントへのスキャンツール提供
MCP 対応
読み取り専用MCPサーバーが、エージェント向けに`scan_text`と`scan_paths`を公開します。継続的なJSONLリクエスト、進捗通知、キャンセルにも対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
2掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| path | string | いいえ | 論理ファイル名です。ディスクからは読み込まれません。デフォルトは stdin です。 |
| text | string | はい |
詳細
Keyspoor
AI コーディングワークフロー向けのオフラインシークレットスキャン。 Keyspoor は、ファイル、Git のステージ済み変更、ローカルの Git 履歴、ZIP/tar/gzip アーカイブをスキャンし、値を伏せた JSON、JSONL、SARIF 形式の結果を出力します。ネイティブ CLI、再利用可能な Rust ライブラリ、読み取り専用 MCP サーバーとして利用できます。MCP 経由でエージェントを接続できます。ステージ済みフックまたは必須の CI チェックを使って、コミットやマージをブロックできます。
ウェブサイト · Rust API · crates.io · npm · リリース · 簡体字中国語
60 秒で試す
Node.js 20 以降を使い、macOS/Linux のターミナルに次のコードを貼り付けます。以下の値はこのデモ用に作成したもので、認証情報ではありません。
printf 'password=KspDemo_7zQ2mX9pL4vN6sR8\n' | npx -y [email protected] scan - --format json
echo "exit=$?"
期待される結果は、exit=1 と検出結果 1 件です。関連するレポート項目は次のとおりです。
{"complete":true,"findings":[{"rule_id":"generic-credential-unquoted","path":"stdin","line":1,"column":9,"redacted":"[REDACTED]"}],"errors":[]}
これは抜粋です。実際のレポートには範囲、フィンガープリント、統計、スキャンコンテキストも含まれます。値やソースの抜粋は含まれません。
Windows PowerShell では、同じ合成文字列を
npx.cmd -y [email protected] scan - --format json にパイプで渡し、$LASTEXITCODE を確認してください。
コミットがブロックされ、修正後に受け入れられる様子を見る

Git とインストール済みの keyspoor CLI を使い、チェックアウトからデモ全体を実行します。
sh examples/first-scan.sh
一時リポジトリを作成し、自身で削除します。この録画は、作成した入力を使った実際の 0.1.3 の実行からのものです。検出時の終了コードは 1、コミットはブロックされ、修正後の終了コードは 0、コミットは受け入れられました。このフックのデモにはエージェントは関与しません。 MCP の設定ではエージェントにツールを提供しますが、各コミットの前にエージェントがツールを呼び出す保証はありません。CI とフックを使うと強制できます。
| 目的 | こちらから |
|---|---|
| リポジトリまたはステージ済み変更をスキャンする | CLI コマンド |
| プルリクエストをブロックしてレポートを保存する | CI の完全な設定 · コピーして使えるワークフロー |
| コーディングエージェントにスキャンツールを提供する | Codex、Claude Code、Cursor の設定 |
| Rust にスキャナーを組み込む | ライブラリの例 · Rust API |
インストール
# Rust toolchain (1.96 or newer)
cargo install keyspoor --version 0.1.4 --locked
# Or Node.js 20+: the npm package runs the native Rust CLI
npm install -g [email protected]
# Or Homebrew (macOS / Linux)
brew install majiayu000/tap/keyspoor
keyspoor scan . --format jsonl
現在のリリース:0.1.4。Rust API は 1.0 より前のバージョンのため、変更される可能性があります。npm パッケージには、macOS(Apple Silicon/Intel)、Linux GNU(ARM64/x64)、Windows x64 向けのネイティブバイナリが同梱されています。これは CLI ランチャーであり、JavaScript のスキャン SDK ではありません。インストールフックや実行時のバイナリダウンロードはありません。npm/npx の初回インストールにはレジストリへのアクセスが必要ですが、スキャン自体はオフラインで実行されます。
スタンドアロンバイナリも利用できます。ソースからビルドするには、cargo build --release --locked を実行し、target/release/keyspoor を使用してください。
Keyspoor を選ぶ理由
- オフラインを前提に設計: スキャン時に認証情報プロバイダーを呼び出さず、レポートには生のシークレットやソースの断片を含めません。
- 再利用可能な Rust エンジン: ルールを一度コンパイルすれば、複数の呼び出しやスレッド間で
Engineを共有できます。スキャナー SDK への依存もありません。 - エージェント向けインターフェース: MCP
scan_text/scan_paths、永続的な JSONL リクエスト、進捗とキャンセルに加え、不完全なスキャンを明示的に報告します。 - リポジトリを考慮した入力: ステージ済みインデックスの内容、ローカル Git 履歴、展開範囲を制限したアーカイブ、無視ファイル、フィンガープリントベースラインに対応します。
- 確認可能なエビデンス: バージョン管理されたルール、文書化された除外項目、再現可能な品質・スループット・アロケーションの測定結果を備えています。
マッチング、キーワードの振り分け、フィルタリング、デコード、位置のマッピング、Git からの取得、エージェント向けインターフェースをこのプロジェクトで実装しています。Kingfisher やその他のシークレットスキャナー SDK には依存しません。汎用的な Rust の正規表現、Aho–Corasick、ハッシュ、アーカイブ用ライブラリを使用しています。
組み込みカタログには、MIT ライセンスの Gitleaks v8.30.1 カタログをベースにした 221 個のルールと、独自に作成した 4 個のルール(汎用的な代入ルール 3 個と URI パスワードルール 1 個)が含まれており、デフォルトのエンジンでは合計 225 個のルールを使用します。ルールの出典と除外項目およびサードパーティに関する通知を参照してください。これは Gitleaks 互換のエンジンではありません。維持できないルールのセマンティクスは明示的に除外しています。実装上の決定には、ビルドと適応の境界、および却下した SDK とラッパーの代替案を記録しています。
CLI とリポジトリのスキャン
keyspoor scan /path/to/project --format json
keyspoor staged /path/to/repository
keyspoor history /path/to/repository
keyspoor history /path/to/repository --range main..HEAD
keyspoor scan - --format jsonl
keyspoor scan /path/to/project --write-baseline baseline.json
keyspoor scan /path/to/project --baseline baseline.json
keyspoor rules
keyspoor serve
keyspoor mcp --root /path/to/project
バージョン 0.1.4 では、認証情報コンテキストの照合とエンジン設定の 識別情報が変更されています。以前のベースラインを確認し、再作成してください。修正結果と ベンチマークを参照してください。
終了コード:0 は選択したスキャンが検出事項なしで完了したことを示します。 1 は検出事項ありで完了したことを示します。2 はエラーまたは未完了のスキャンを示します。 合成入力を使って、ほかの 2 つの結果も確認できます。
printf 'ordinary configuration\n' | npx -y [email protected] scan - --format json
echo "exit=$?" # 0: complete=true, findings=[]
printf 'ordinary configuration\n' | npx -y [email protected] scan - --max-bytes 4 --format json
echo "exit=$?" # 2: complete=false, errors contains "input exceeds 4 byte limit"
検出事項が見つかった場合は、該当するパスと位置をローカルで確認し、追跡対象ファイルから
露出した認証情報を削除して、実際に露出した認証情報があればローテーションしてください。
ベースラインを記録する前に、既知の意図的な検出事項を確認してください。スキャンが完了したと
判断する前に、すべての 2 の結果を調査してください。
無視された検出事項は、元の入力にシークレットが含まれていなかった証拠にはなりません。
ベースラインは既存のフィンガープリントを抑制しますが、変更されたシークレット値は保持します。
未完了のスキャンでベースラインを置き換えることはできません。ベースラインスキーマ 2 は、
スキャンモード、正規化されたルート、実効的な無視ポリシー(Git/Jujutsu のリポジトリ境界を含む)、
サイズ上限、エンジン設定
(ルールの内容とフィンガープリントキーの識別情報を含む)を関連付けます。
スコープやポリシーが異なる場合、そのベースラインとの比較や上書きはできません。
ポリシーを意図的に変更する場合は、別のベースラインを作成してください。スキーマ 1 のベースラインは拒否されます。
ファイルシステムの正規化された識別情報により、./ のようなエイリアスは安定します。報告されるパスとルールの
パス述語は、選択したソースルートからの相対パスのままです。
すべての検出事項は編集されており、ルール、パス、バイト範囲、1 始まりの行番号、
0 始まりのバイト列の列番号、信頼度、説明、フィンガープリントが含まれます。生のシークレットや
ソースのスニペットがシリアル化されることはありません。デフォルトの非キー付きフィンガープリントはダイジェストであり、
暗号化でも、エントロピーの低いシークレットの推測を防ぐものでもありません。キー付き BLAKE3 識別子を使用するには、
プライベートな 32 バイトちょうどのキーを指定して --fingerprint-key-file を使用してください。
ベースラインを比較する際は、同じプライベートキーを使用してください。
同じデコード済みビュー内で、同じシークレットのバイト範囲にある完全一致は統合されます。
rule_id は主ルールを識別します。generic- 以外の ID が優先され、次に信頼度の高さ、
それからルール ID の辞書順で決まります。統合された検出事項には、主ルールと一致したほかのルールを含む
ソート済みの matched_rule_ids が含まれます。単一ルールの検出事項ではこのフィールドは省略されます。
隣接する出現箇所、部分的な重なり、1 つの Base64 コンテナー内の異なる位置は別々に扱われます。
主ルールによってフィンガープリントが決まります。この意味上の更新によりエンジン設定の識別情報が変更されるため、
以前のベースラインを暗黙に比較するのではなく、明示的に再作成する必要があります。
スキャンで認証情報プロバイダーに接続したり、認証情報が有効かどうかを検証したりすることはありません。
ファイルシステムのスキャンでは、デフォルトで無視ファイルに従います。--no-ignore を指定すると、
無視対象のファイルも含まれますが、Git メタデータは引き続き除外されます。サイズ超過の入力はクリーンではなく、
未完了として報告されます。ファイルとアーカイブのデフォルトの展開上限は 64 MiB です。
--max-bytes で上限を変更できます。アーカイブの走査でメンバーがディスクに書き込まれることはありません。
ZIP、tar、gzip は共通の展開上限を共有し、入れ子の深さは最大 4 レベルです。
暗号化されたメンバーや破損したメンバーは、エラーとして表示されます。
ステージ済みモードでは、変更された各ファイルの作業ツリー版ではなく、index 版を読み込みます。
認証情報ペアのコンテキストを維持するため、ステージ済みファイル全体をスキャンします。履歴モードでは、
ローカルから到達可能なコミットをスキャンし、各一意の blob を 1 回だけ読み込み、コミットとパスの出現箇所を保持します。
LFS、サブモジュール、リモート参照は取得しません。また、Git blob 内の対応アーカイブも展開し、
コミットとメンバーのパスを保持します。stats.files/bytes は一意な入力の数を数え、
detection_passes は実際にパス依存のエンジン呼び出しが行われた回数を数えます。
GitHub Action
完全なプルリクエストのワークフローを
.github/workflows/keyspoor.ymlにコピーするか、レポート、権限、ベースライン、失敗処理については
CI セットアップガイドに従ってください。スキャンジョブは
ブランチ保護の必須チェックに設定できます。主な手順は次のとおりです。
permissions:
contents: read
steps:
- uses: actions/checkout@v7
- uses: majiayu000/keyspoor@v1
id: secrets
with:
path: .
format: sarif
- uses: actions/upload-artifact@v7
if: always() && steps.secrets.outputs.report-path != ''
with:
name: keyspoor-report
path: ${{ steps.secrets.outputs.report-path }}
これらの手順をジョブに配置してください。この Action はソース参照に記録された正確な npm パッケージバージョンをインストールし、選択したパスをスキャンして、チェックアウトの外部に秘匿化されたレポートを保存します。report-pathはそのファイルを指し、exit-codeは0(問題なし)、1(検出結果あり)、2(エラー/不完全)を保持します。検出結果とエラーがあるとステップは失敗します。エラー後のレポートは不完全な場合があります。Action を変更不可の状態で固定するには、維持管理されているv1参照ではなく、完全なコミット SHA を使用してください。対応するレポート形式は SARIF(デフォルト)、JSON、JSONL です。インストールには npm レジストリへのアクセスが必要ですが、検出自体はオフラインで実行されます。Action はファイルをスキャンします。ステージ済みファイル/履歴モードやカスタムエンジンオプションには CLI を使用してください。
リリースは npm および crates.io の信頼された公開を使ってGitHub Actions経由で公開されます。既存の tap における Homebrew の更新は1時間ごとに実行され、GitHub のスケジューリングによって遅れる場合があります。トリガーと検証については リリースガイドを参照してください。
ライブラリとカスタムルール
この例では、依存関係にkeyspoor = "0.1"とanyhow = "1"を追加してください。
use keyspoor::{Engine, EngineConfig};
fn main() -> anyhow::Result<()> {
let engine = Engine::new(EngineConfig::default())?;
let findings = engine.scan_bytes("config.env", b"ordinary configuration")?;
assert!(findings.is_empty());
Ok(())
}
呼び出しのたびにコンパイルを繰り返さないよう、エンジンを複数の呼び出しやスレッドで再利用してください。グローバルランタイム、ロガー、エグゼキューターはインストールしません。
Finding.pathとFinding.explanationは、共有されるArc<str>値です。これはStringからの破壊的な Rust API 変更です。所有文字列を割り当てる場合は.into()を使い、&strとして読み取る場合は.as_ref()を使い、テキストを変更する場合はフィールドを置き換えてください。JSON には引き続き通常の文字列が含まれます。フィンガープリント、スキャンコンテキスト、ベースラインの識別情報に変更はありません。生成された検出結果は、1回のエンジンスキャン内ではパスを共有し、同じエンジンを使用する呼び出し間では説明を共有します。デシリアライズ時に重複した文字列はインターン化されません。
カスタム JSON ルールファイルでは{"rules": [...]}を使用し、--rules path.jsonまたはルールディレクトリを指定できます。--no-builtinを指定すると、カスタムルールのみが選択されます。各ルールにはid、name、pattern、任意のsecret_group、keywords、min_entropy、confidence、path、allowlist、exclude_pathsがあります。キーワードは大文字と小文字を区別せず、OR 条件で必要条件として評価されます。キーワードのないルールは常に考慮されます。許可リストグループには、condition(or/and)、target(secret/match/line)、regexes、paths、stopwordsがあります。グループは OR 条件で結合されます。同じカテゴリ内の述語は OR 条件で結合され、その後、値が設定されたカテゴリがconditionに従って結合されます。ストップワードは、シークレットに含まれる大文字と小文字を区別しない部分文字列です。空のグループは失敗します。secret_groupを省略またはnullにすると、最初の空でないキャプチャ(またはマッチ全体)が選択されます。明示的に0を指定すると、マッチ全体が選択されます。これらのルールスキーマの変更は破壊的変更です。不明なルールフィールドや無効な正規表現がある場合は、明示的に失敗します。コンパイルエラーにルールパターンが出力されることはありません。カスタムルールの説明と識別子は信頼された設定値であり、実際のシークレットを含めないでください。
汎用的な API/アクセス/認証トークンの代入では、長い説明文(8語以上で、文または節の句読点を含む)を抑制します。このヒューリスティックは自然言語によるパスワード/シークレットの代入を抑制しませんが、長く句読点を含む語句として記述された実際のトークンを見逃す場合があります。プロバイダーのルールには上流の制限が引き継がれます。ルールの由来に関するドキュメントを参照してください。
エージェントインターフェース
まず、Codex、Claude Code、Cursor 向けのテスト済み設定ガイドを確認してください。 MCP は読み取り専用ツールを公開します。エージェントがツールを呼び出すかどうかは、クライアント、その権限、タスクによって異なります。スキャンを変更の受け入れ前に必ず実行する必要がある場合は、必須の CI チェックまたは Git フックを使用してください。
serve は、1 行につき 1 つの JSON オブジェクトを受け付けます:{"id":1,"path":"file.txt","text":"..."}。
応答には同じ id と、マスキング済みの完全なスキャンレポートが含まれます。ルールは一度だけコンパイルされます。不正な JSON に対してはペイロードをそのまま返さずにエラーを返し、リクエストが大きすぎる場合は、このシンプルなストリームを終了します。
MCP stdio サーバーは、初期化、ping、ツール一覧表示、および scan_text と scan_paths の呼び出しをサポートします。ファイルパスは設定済みのルート配下に解決される必要があります。サーバーは書き込みもネットワーク検証も行いません。ルートチェックは、別のローカルプロセスがパスを同時に置き換えることを防ぐ OS サンドボックスではありません。MCP エラーとツールの失敗は区別され、不正なフレームやサイズ超過のフレームが、スキャン成功として扱われることはありません。stdout にはプロトコルメッセージのみが出力されます。スキャンは一度に 1 つ実行されますが、ping とキャンセルには引き続き応答します。クライアントは進捗トークンを指定でき、リクエスト ID でキャンセルできます。キャンセルされたリクエストには最終応答が返されず、セッションは引き続き使用できます。キャンセルはファイル、Git blob、アーカイブメンバーの境界(アーカイブの読み取りチャンクも含む)で確認されますが、単一の正規表現処理の途中では確認されません。ツールの結果には、合計件数と output_truncated に加えて、共通の 512 KiB エントリ予算内で最大 100 件の検出結果と 100 件のエラーが含まれます。出力の切り詰めとスキャンの完全性は、それぞれ独立しています。
JSON、JSONL、SARIF を利用できます。通常のファイルシステム/Git の JSONL スキャンでは、スキャン中に finding、error、progress レコードが出力され、その後、件数と完全性を含む summary が出力されます。上限付きワーカキューにより、すべてのファイルレポートを収集せずに済みます。出力エラーが発生すると、それ以上の取得は停止します。各ワーカーは引き続き 1 つの入力とその検出結果をバッファーに保持し、Git 履歴のメタデータもメモリ上に保持されます。JSON/SARIF、stdin、およびベースラインを使用する JSONL スキャンではレポートを収集します。フィルター適用済みの結果を出力する前に、ベースラインの検証を完了する必要があります。SDK の呼び出し元は、ScanControl と失敗を返すイベントシンクを使って scan_*_stream API を利用できます。通常の進捗は最大で 100 ms に 1 回出力され、最初と最後のスナップショットは保持されます。これらはイベント駆動型の更新であり、単一の長時間にわたる正規表現処理中のハートビートではありません。CLI は最初の検出結果と各エラーを即座にフラッシュし、以降の検出結果はバッファーに書き込みます。進捗レコードと最終レコードでは、残りの出力がフラッシュされます。
検証と比較
cargo fmt --check
cargo test --locked
cargo clippy --all-targets --locked -- -D warnings
python3 -m unittest discover -s bench -p test_run.py
python3 bench/fixtures/generate.py --self-test
python3 scripts/import_rules.py --check
python3 -m unittest discover -s bench -p test_holdout.py
python3 -m unittest discover -s scripts -p test_stress_benchmark.py
python3 scripts/check_package.py --allow-dirty
独立した合成評価には、固定された88件のホールドアウト、その見逃しと誤検出、ベースラインのワークフローの制限が記録されています。ベンチマークの手法と再現方法では、ラベル付き合成データの品質と、ラベルなしの実ソースに対するスループットを分けて評価しています。バージョン、コマンド、ハードウェア、バイナリのフィンガープリント、時間、メモリ、パーサーの完全性、未対応機能を保持しています。オンライン検証は無効になっています。これらの測定値は、本番環境での精度や、あらゆる状況における速度の優位性を示すものではありません。
最新のv6 の割り当てとパフォーマンスのレポートでは、Apple M2 Max/macOS で交互に実施した20組の変更前/変更後の測定を行いました。100,000件の検出結果を含む合成 JSONL ワークロードでは、スキャナーのピーク RSS が99.86 MiBから59.59 MiBに減少し、スキャナーの CPU 時間が8.74%短縮しました。通常のスループットと Git ワークロードはおおむね変わりませんでした。これらはこのプロジェクト内での変化であり、競合ツールとの速度ランキングではありません。以前に確認された合成データの回帰セットでは、真陽性600件、偽陽性25件、偽陰性0件が保持されています。これは実環境での適合率の推定値ではありません。
測定結果、バージョンごとのツール間比較、比較手法、機能ごとの調査を参照してください。この調査では22件の外部プロジェクトを取り上げています。未対応、利用不可、クラウド依存の項目は、失敗として採点せず、その旨を明示しています。過去の成果物では、Keyspoor になる前のプロジェクト名である secret-scan が使われています。記録されていたコマンドとバイナリのハッシュは保持されています。
機能実装マトリックスでは、調査カタログの各項目について、実装済み、一部実装、未実装のいずれかを示しています。CLI または MCP サーバーがあるからといって、クラウドコネクター、認証情報の検証/失効、GPU/ML バックエンド、言語バインディングが利用できることを意味するわけではありません。
ライセンスとサポート
Keyspoor はApache-2.0 ライセンスのもとで提供されています。適用されたルールデータには、THIRD_PARTY_NOTICESに記載されている上流の MIT ライセンスと帰属表示が引き継がれています。再現可能なバグの報告や機能のリクエストは、GitHub Issuesで行ってください。合成例を使用し、実際の認証情報は含めないでください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。