shimguard について
ShimGuardは、修正済みとされたGitHub issueが、実際にマージされたプルリクエストを引用しているかを確認します。HEADに脆弱なコードパターンが残っているかも検査でき、トラッカーの記載を検証するメンテナーやセキュリティチーム、CI向けです。
主な機能
- 01引用されたPRのマージ状態を確認
- 02HEADのコードパターンを任意で検査
- 03MATCH、MISMATCH、UNVERIFIEDの判定
- 04スクリプトやエージェント向けJSON出力
- 05CI向け終了コード
活用シーン
- 01クローズ済みセキュリティissueの修正状況を監査
- 02issueが引用する未マージ修正をCIで検出
- 03引用された脆弱コードパターンの残存を確認
MCP 対応
MCPサーバーはrunツールを1つ公開し、shimguard CLIの引数を受け取って構造化結果を返します。JSON出力がある場合は解析結果も含まれます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
ShimGuard
GitHub のイシューが「修正済み」としてクローズされているとき、トラッカーを信頼する前に、実際に修正がマージされているかを検証します。

npx shimguard-cli verify sybil-solutions/codex-shim --issues 38,41,42,43,45,46
実際の sybil-solutions/codex-shim リポジトリ(スター数 1,000 以上)に対してこのコマンドを実行すると、6 件の MISMATCH 結果が見つかります。6 件のセキュリティイシューにはそれぞれ「Fixed in PR #52」というコメントが付けられてクローズされていますが、PR #52 は実際には一度もマージされていません。脆弱なコードは、現在も main に残っています。クローズ済みのイシューを読むだけでは、誰も気づけません。
目次
これが必要な理由
イシュートラッカーを読むとき、信頼する情報は 2 つあります。イシューの state(open または closed)と、メンテナーのクローズコメント(「fixed in #N」)です。どちらの情報も、GitHub 自体によって実際の状況と照合されているわけではありません。メンテナーがマージされていない PR を挙げてイシューをクローズしたり、自動ボットが PR の説明にある「fixes #N」というキーワードを見て、その PR が取り込まれる前にイシューをクローズしたり、イシューがクローズされた後に修正がリバートされたりすることがあります。いずれの場合も、バグがまだ存在するのに、トラッカーには「修正済み」と表示されます。
ShimGuard は、イシューをざっと読む人が確認しない 1 つの点をチェックします。トラッカーが修正として挙げている PR に、実際に merged: true が表示されているかどうかです。これは小規模で機械的な、明確なチェックであり、ヒューリスティックや推測ではありません。
インストール
ShimGuard には、同等に正式な 2 つの独立したパッケージがあります。ツールチェーンに合う方を選ぶか、両方をインストールしてください。どちらかがもう一方に置き換えられる予定はありません。どちらも同じ GitHub REST API に対して、「クローズ済みのイシューに Fixed in PR #N と記載されているとき、#N は実際にマージされているか」を同じ方法でチェックします。
# npm -- JavaScript/TypeScript CLI + library
npm install -g shimguard-cli
# or run it once with no install
npx shimguard-cli verify <owner>/<repo> --issues <numbers>
# PyPI -- Python CLI + library (genuine port, not a wrapper around the Node binary)
pip install shimguard-cli
npm の CLI には Node.js 18 以降が必要です(組み込みの fetch API を使用します)。Python パッケージの CLI エントリポイントも shimguard です(例:shimguard verify sybil-solutions/codex-shim --issues 45,46)。Python 固有の手順については python/README.md と docs/getting-started.md を、各配布版のバージョン履歴については CHANGELOG.md を参照してください。
クイックスタート
shimguard verify sybil-solutions/codex-shim --issues 38,41,42,43,45,46
ShimGuard v0.1 -- Tracker Verification: sybil-solutions/codex-shim
[MISMATCH] Issue #45 "_resolve_api_key silently falls back to Cursor API key for any model with an empty api_key, forwarding it to arbitrary upstream URLs"
https://github.com/sybil-solutions/codex-shim/issues/45
Cited fix: PR #52 (open, not merged)
Issue is closed and cites PR #52 as the fix, but that PR is open and was never merged.
Summary: 6 MISMATCH, 0 MATCH, 0 UNVERIFIED (6 checked)
いずれかの MISMATCH が見つかった場合、終了コードは 1 です(CI のゲートに便利です)。チェック対象のすべてのイシューで、記載された修正が実際にマージされている場合は 0、使用方法またはネットワークのエラーが発生した場合は 2 です。
ShimGuard は、見落としを見つけるだけのツールではありません。さまざまなイシューをまとめて実行すると、MATCH、UNVERIFIED、MISMATCH を並べて正しく報告します。証明できる問題がなければ常に終了コード 0 となり、CI ゲートに必要なシグナルをそのまま提供します。

オプション:マージ状況だけでなく、コードも検証する
さらに確実に確認するには、脆弱なコードとして課題に記載された 特定のファイルとパターンを ShimGuard に指定します。
cat > patterns.json <<'EOF'
{
"45": { "path": "codex_shim/settings.py", "pattern": "cursor_key_fallback" }
}
EOF
shimguard verify sybil-solutions/codex-shim --issues 45 --patterns patterns.json
PR がマージされていても、引用されたパターンが HEAD 時点でファイルに
残っていれば、ShimGuard は引き続き MISMATCH を報告します。PR がマージされても、
問題のある特定の行が実際に削除されたとは限りません。
警告
patternは JavaScript のRegExpとしてコンパイルされ、pathは対象のリポジトリ内に とどまるよう検証されます(別のリポジトリや API エンドポイントへの..によるパス移動はできません)。--patternsは、自分で作成またはレビューした ファイルのみを指定してください。SECURITY.md を参照してください。
CLI リファレンス
Usage: shimguard [options] [command]
Verify that GitHub issues closed as "fixed" actually have a merged fix. Catches
security issues marked fixed whose PR was never merged.
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
verify [options] <repo> Check whether closed issues in a repo actually have
a merged fix
help [command] display help for command
Usage: shimguard verify [options] <repo>
Check whether closed issues in a repo actually have a merged fix
Arguments:
repo target repo as <owner>/<repo>, e.g.
sybil-solutions/codex-shim
Options:
--issues <numbers> comma-separated issue numbers to check, e.g. 38,41,42
--patterns <file> JSON file mapping issue number -> {path, pattern} for an
optional code-pattern check
--token <token> GitHub token for higher API rate limits (defaults to
$GITHUB_TOKEN)
--format <format> output format: text or json (default: "text")
-h, --help display help for command
--format json の出力は安定しており、スクリプトや AI エージェントが
直接解析できるように設計されています。
{
"repo": "sybil-solutions/codex-shim",
"checked": 1,
"summary": { "mismatch": 1, "match": 0, "unverified": 0 },
"results": [
{
"issue": { "number": 45, "title": "...", "state": "closed", "htmlUrl": "..." },
"citedPullRequest": { "number": 52, "state": "open", "merged": false, "htmlUrl": "..." },
"patternCheck": null,
"verdict": "MISMATCH",
"reason": "Issue is closed and cites PR #52 as the fix, but that PR is open and was never merged."
}
]
}

MCP サーバー
ShimGuard には Model Context Protocol サーバーが付属しているため、MCP 互換のエージェント (Claude Desktop、Claude Code、Cursor、その他の MCP クライアント)が、CLI を呼び出して テキストを解析する代わりに、ツールとして利用できます。このサーバーは Python ディストリビューションの一部です。
pip install "shimguard-cli[mcp]"
Claude Desktop などの MCP クライアントに登録します。
{
"mcpServers": {
"shimguard": {
"command": "shimguard-mcp"
}
}
}
このサーバーは、shimguard CLI に渡すものと同じ argv を受け取る単一のツール run を公開し、
構造化された結果を返します(成功時は {returncode, stdout, stderr, json?}、コマンドの失敗、タイムアウト、またはゼロ以外の終了コードの場合は
{error: ...})。呼び出し例:
run(args=["verify", "sybil-solutions/codex-shim", "--issues", "45,46", "--format", "json"])
この呼び出しは、上記と同じ --format json レポートを返します。解析済みの
json フィールドと、生の stdout が含まれます。詳細は
Python package README を参照してください。
ライブラリ API
ShimGuard の検証ロジックは、直接インポートして利用することもできます。
import { TrackerVerifier, RestGitHubClient, RegexPatternMatcher } from "shimguard-cli";
const client = new RestGitHubClient(process.env.GITHUB_TOKEN);
const verifier = new TrackerVerifier(client, new RegexPatternMatcher(client));
const result = await verifier.verify({ owner: "sybil-solutions", repo: "codex-shim", number: 45 });
console.log(result.verdict); // "MISMATCH"
TrackerVerifier は任意の GitHubClient と省略可能な PatternMatcher
(src/types.ts、src/pattern-matcher.ts を参照)を受け取ります。どちらもインターフェースなので、
将来的にローカル設定スキャナーや別のコードホストを、検証器自体を変更せずに接続できます。
Python パッケージでも同じ形式を利用できます。
from shimguard import TrackerVerifier, RestGitHubClient, RegexPatternMatcher, IssueRef
client = RestGitHubClient() # or RestGitHubClient(token=os.environ["GITHUB_TOKEN"])
verifier = TrackerVerifier(client, RegexPatternMatcher(client))
result = verifier.verify(IssueRef(owner="sybil-solutions", repo="codex-shim", number=45))
print(result.verdict) # "MISMATCH"
比較
「このイシュートラッカーには修正が PR #N で完了したと書かれているが、#N は実際にマージされているのか」を確認する既存のオープンソースツールはありません。この主張は、これを記述する前に、イシュー修正確認ツール、パッチ検証ツール、セキュリティアドバイザリー修正ツールを検索して確認しました。最も近い関連ツールは、別の問題を解決します。
| ツール | 実際に確認する内容 | イシュートラッカー/PR のマージ状態を読み取るか |
|---|---|---|
| ShimGuard | GitHub のイシューに記載された「PR #N で修正済み」という主張が、PR #N の実際のマージ状態と一致するか(また、オプションで、引用されたコードパターンが HEAD からなくなっているか) | はい。これが確認のすべてです |
| gitleaks / trufflehog | ソースにコミットされたシークレット(API キー、トークン) | いいえ。トラッカーの状態ではなく、ファイルの内容をスキャンします |
| trivy / grype / osv-scanner | 依存関係ツリーに含まれる既知の CVE | いいえ。トラッカーの状態ではなく、依存関係マニフェスト/ロックファイルをスキャンします |
| Vanir(Google) | 既知の CVE のコードシグネチャが、対象のソースツリーにまだ存在するか | いいえ。CVE からコードを調べるもので、GitHub のイシュートラッカーには触れません |
| VFCFinder(NC State、ASIACCS 2024) | まだ修正リンクがないアドバイザリーについて、修正コミットの候補を見つけます | 逆方向です。記載漏れを見つけるもので、既存の記載を検証しません |
ShimGuard が埋めるギャップは、理論上のものではなく実在します。wow-actions/auto-close-fixed-issues は、ほかのリポジトリでも使われている GitHub Action ですが、PR の merged イベントではなく closed イベントでイシューをクローズします。そのため、PR が実際にマージされたかどうかにかかわらず、ボットが PR のクローズと同時にイシューを「修正済み」とマークすることがあります。GitHub 標準の Closes #N キーワードによるリンクでは、デフォルトブランチへの実際のマージ時にのみ自動クローズされます。つまり、この特定の障害モードは、GitHub 自体のデフォルト動作ではなく、メンテナーによる手動コメントやサードパーティーの自動化によって発生します。だからこそ、事後にこれを検出するものがありません。
ShimGuard とは何か、なぜ存在するのか
ShimGuard は CLI およびライブラリで、npm パッケージと PyPI パッケージの両方として提供されています。GitHub のイシューに記載された修正(「PR #N で修正済み」)が実際に正しいかどうかを、その PR の実際のマージ状態を確認して検証します(また、オプションで、脆弱なコードパターンが HEAD にまだ存在するかどうかも確認します)。未マージの PR を引用してイシューをクローズすることは、仮定上の問題ではなく、実際に確認されている障害モードです。執筆時点で、1,000 以上のスターを獲得している sybil-solutions/codex-shim プロジェクトでは、6 件のセキュリティイシューがこの方法でクローズされており、いずれも同じ未マージの PR #52 を引用しています。ShimGuard は、ソースコード内のシークレットをスキャンするものではありません(その用途には gitleaks、trufflehog をご覧ください)。また、依存関係に対する一般的な脆弱性スキャンも行いません(その用途には osv-scanner、trivy、grype をご覧ください)。検証するのは、特定の狭い範囲の主張です。つまり、トラッカーの「修正済み」というステータスが実態と一致しているかどうかです。
FAQ
ShimGuard は自分のリポジトリや対象のリポジトリを変更しますか? いいえ。読み取り専用の GitHub API リクエスト(イシュー、コメント、プルリクエスト、および任意でファイルの内容)を行うだけです。書き込み、コメントの投稿、変更は一切行いません。
GitHub トークンは必要ですか?
たまに使う程度であれば必要ありません。認証なしのリクエストも利用できますが、GitHub の標準レート制限(1 時間あたり 60 リクエスト)が適用されます。より高い認証済みレート制限(1 時間あたり 5,000 リクエスト)を利用するには、GITHUB_TOKEN を設定するか、--token を渡してください。CI での利用に便利です。
「引用された修正」とは何ですか?
ShimGuard はイシュー本文とコメント内から、「Fixed in PR #52」「fixed by #101」「resolved in #20」のような表現を探し、参照されている PR 番号を抽出します。このような表現が見つからない場合、結果は MATCH や MISMATCH ではなく UNVERIFIED になります。ShimGuard が推測することはありません。
CI で使えますか?
はい。shimguard verify は MISMATCH が見つかると終了コード 1 を返すため、CI のステップで直接ゲートとして使用できます。--format json を指定すると、ボットやダッシュボードで安定して解析できるレポートが得られます。
BYOK shim の設定をスキャンしないのに、なぜ「ShimGuard」なのですか?
このアイデアは当初、BYOK(bring-your-own-key)モデル shim を対象とする、より広範なローカル設定のセキュリティスキャナーとして構想されていました。この範囲は、トラッカーの主張を実際にマージされたコードと照合するという、より明確で正当化しやすい領域に絞られ、v0.1 ではその機能がリリースされました。この名前はプロジェクトの出発点(BYOK モデル shim である sybil-solutions/codex-shim)を反映したもので、このバージョンにない機能範囲を示すものではありません。
ShimGuard は Windows、macOS、Linux で動作しますか?
npm CLI には Node.js 18 以降(組み込みの fetch API を使用するため)が必要で、Windows、macOS、Linux を含め、Node が動作する環境であればどこでも実行できます。PyPI パッケージには Python 3.9 以降が必要で、パッケージ自身の分類情報では OS Independent とされています。どちらのパッケージにも、ネイティブ依存関係やコンパイル済みの依存関係はありません。
ShimGuard は gitleaks や trufflehog とどう違いますか? Gitleaks と trufflehog は、API キーやトークンなど、誤ってリポジトリにコミットされたシークレットを探すためにファイルの内容をスキャンします。ShimGuard はシークレットを探す目的でファイルの内容をスキャンすることは一切ありません。確認するのは GitHub のイシューおよびプルリクエスト API で、具体的には「PR #N で修正」としてクローズされたイシューの PR #N が実際にはマージされていない、という不一致です。この 2 種類のツールはそれぞれ異なる障害モードを検出するため、互いに重複せず同じパイプラインで実行できます。コードを書き始める前にこのプロジェクトが確認した関連ツールの全リストについては、上記の「比較」を参照してください。
shimguard --version がインストール済みパッケージと異なる番号を表示することがあるのはなぜですか?
過去の一部のリリースでは、shimguard --version がインストール済みパッケージの実際のバージョンより古いバージョン文字列を報告していました。src/cli.ts の commander に渡されるバージョン文字列が、package.json のバージョン更新と同じリリースで必ずしも更新されていなかったためです。これは表示上だけの不一致であり、verify の動作には影響しません。実際にインストールされているバージョンを確認するには、パッケージ自身の package.json を読むか、npm view shimguard-cli version を実行してください。
ShimGuard はリポジトリ内のクローズ済みイシューをすべて自動的にスキャンしますか?
いいえ。確認するイシュー番号は --issues 38,41,42 を指定して渡します。ShimGuard は現時点では、引用された修正に関する主張を探して、リポジトリのクローズ済みイシューの履歴全体を自動で調べることはありません。大規模なリポジトリでは、たとえば security タグが付いたイシューやリリースマイルストーンに関連するイシューなど、確認したいものを選んでください。
商用製品や有料の CI パイプラインで ShimGuard を使えますか? はい。ShimGuard は MIT ライセンス(LICENSE を参照)で提供されており、有料製品や社内ツールへの組み込みを含め、商用利用、変更、再配布が認められています。ロイヤリティは不要で、自分のコードをオープンソースにする義務もありません。MIT の告知を保持することだけが条件です。
貢献
CONTRIBUTING.md を参照してください。
セキュリティ
SECURITY.md を参照してください。
ライセンス
MIT。LICENSE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。