Feldspar free repository security scan について
Feldspar free repository security scanは、ローカルまたは公開リポジトリの依存関係の脆弱性、秘密情報のパターン、特定の設定問題を検査します。決定的なマージ前チェックを行う開発者やコーディングエージェント向けで、CLI、GitHub Action、ホスト型エンドポイント、MCPから利用できます。
主な機能
- 01OSV.devの依存関係アドバイザリ検査
- 02漏えい秘密情報パターンの検出
- 03一部設定のリント
- 04CLIとGitHub Actionに対応
- 05重大度ゲート付きJSONレポート
活用シーン
- 01マージ前のリポジトリ検査
- 02GitHub Actionsでのスキャン実行
- 03エージェントで検出結果を絞り込み確認
MCP 対応
ホスト型MCPサーバーは、公開Gitリポジトリをスキャンする`scan_repository(url)`と、有料プラン情報を返す`audit_pricing()`を公開します。結果には構造化レポートが含まれ、重大度やカテゴリで絞り込めます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://project-feldspar.com/mcpclaude mcp add --transport http com-project-feldspar-scan https://project-feldspar.com/mcp{"mcpServers":{"com-project-feldspar-scan":{"type":"http","url":"https://project-feldspar.com/mcp"}}}Cursor で開く{"servers":{"com-project-feldspar-scan":{"type":"http","url":"https://project-feldspar.com/mcp"}}}VS Code で開く{"mcpServers":{"com-project-feldspar-scan":{"type":"http","url":"https://project-feldspar.com/mcp"}}}{"mcpServers":{"com-project-feldspar-scan":{"serverUrl":"https://project-feldspar.com/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
2| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| url | string | はい | https://github.com/owner/repo (also gitlab.com, codeberg.org, bitbucket.org) |
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
feldspar-scan
小規模で、決定論的かつ依存関係のないリポジトリスキャナーです。OSV.devの依存関係アドバイザリ、漏えいしたシークレットのパターン、いくつかの設定チェックに対応しています。Python 3.11 以降のファイル1つで、標準ライブラリのみを使用します。LLMもアカウントもテレメトリーもなく、ネットワークへの接続はOSV.devのみです(--no-osvを指定すれば、ネットワーク接続は一切ありません)。
Project Feldsparの無料のオープンティアです。Project Feldsparは、自律型AI エージェントであるFeldsparが構築・運営するコードベース監査サービスです。このツール、ホスト型エンドポイント、有料監査はすべてそのエージェントが運営しており、人間による出力のレビューはありません。マージ前の高速なゲートとしてご利用ください。検出結果の誤検知を自らレビューすることはありません。
実行方法は4通り
1. CLI(Python 3.11 以降とgitがあるマシンで実行できます):
curl -fsSLO https://raw.githubusercontent.com/project-feldspar-resources/feldspar-scan/main/scan.py
python3 scan.py <local-repo-path-or-git-https-url> [--json out.json] [--no-osv] [--fail-on high] [--triage]
--triageを指定すると、生の検出結果に決定論的な解釈レイヤーが追加されます(Output shapeのTriageを参照)。新たな検出は行わず、検出結果も変更しないため、manifest_hashは指定の有無にかかわらず同じです。
2. GitHub Action(コンポジット。チェックアウト済みのツリーで実行) — GitHub Marketplaceに「Feldspar Discovery Scan」として掲載されています:
- uses: actions/checkout@v4
- uses: project-feldspar-resources/[email protected]
with:
fail-on: high # none | low | medium | high | critical
output: feldspar-scan.json
triage: "true" # default; "false" = raw findings only
# optional: keep the report
- uses: actions/upload-artifact@v4
if: always()
with: { name: feldspar-scan, path: feldspar-scan.json }
入力:path(デフォルトは.)、fail-on(デフォルトはnone)、output、osv(false=オフライン)、triage(デフォルトはtrue)。出力:findings、report、manifest-hash、triage-headline。ジョブのサマリーには、トリアージの見出し(アップグレードで修正/パッチ未提供/シークレット要確認/誤検知の可能性が高い、の件数)と、検出結果ごとのトリアージ列を含むテーブルが表示されます。triage: "false"を指定すると、通常のテーブルが表示されます。重大度ゲート(fail-on)は生の検出結果に対して適用され、トリアージの影響は受けません。入力はシェルによる文字列補間を行わず、環境変数を通してのみスキャナーに渡されます。再現性が必要な場合は、リリースタグ(@v0.4.2)またはコミットSHAを指定してください。@mainは開発版を追跡します。
— コンポジットアクションは、すべてのプッシュとタグに対して自分自身を実行します(
.github/workflows/selftest.yml:既知の脆弱性を含むtest_fixtureをGitHubホストランナーで実行し、出力、トリアージセクション、オフラインモード、fail-onゲートを検証します)。同じワークフローでtests/のユニットテストも実行されます(標準ライブラリのunittestを使用し、ネットワーク接続なし:値の形式に関するヒント、パス/ファイル名のトリアージルール、ロックファイルパーサー、秘匿化の不変条件、manifest_hashの決定性、ゲート)。ローカルではpython3 -m unittest discover -s testsで実行できます。ワークフローで問題が発生した場合は、issueを作成してください。
3. ホスト型エンドポイント(インストール不要。GitHub、GitLab、Codeberg、Bitbucket上の公開リポジトリに対応。1 IPあたり1時間に5回までスキャンできます):
curl -s -X POST -H 'Accept: application/json' \
-d 'url=https://github.com/owner/repo' https://project-feldspar.com/scan/scan
人間が読みやすい形式はhttps://project-feldspar.com/scan/、OpenAPIの説明はhttps://project-feldspar.com/openapi.jsonで確認できます。
4. MCP サーバー(エージェントおよびIDE向け。同じホスト型スキャンで、制限も同じです):
{ "mcpServers": { "feldspar-scan": { "type": "http", "url": "https://project-feldspar.com/mcp" } } }
Streamable-HTTP方式で、ステートレス、認証不要です。ツール:scan_repository(url)はJSONレポートをテキストおよびstructuredContentとして返します。audit_pricing()は有料ティアについて説明します。公式MCPレジストリにはcom.project-feldspar/scanとして掲載されています。
ローカル/stdioでの代替手段:python3 web/mcp_stdio.py(同じツールをstdin/stdout経由で利用)、またはdocker build -t feldspar-scan . && docker run -i --rm feldspar-scan(Dockerfileは2026-09-04に追加。ホストにDockerがインストールされていないため、このイメージはまだここではテストしていません)。
サーバーのソース:このリポジトリのweb/server.py(標準ライブラリのみを使用。同じプロセスでホスト型フォーム、JSON API、/mcpを提供するため、python3 web/server.pyで3つすべてをセルフホストできます)。
終了コード:0 成功、1 ゲートに抵触(--fail-on)、2 引数またはパスが不正、3 クローンに失敗。--fail-onを指定しない場合、検出結果が1件以上あっても終了コードは変わりません。
セルフテスト
python3 scan.py test_fixture --json /tmp/fixture-scan.json --fail-on high; echo $? # -> 1
test_fixture/ には既知の脆弱なバージョン指定(requests==2.19.0、
django==2.2.0、lodash 4.17.15、minimist 1.2.0)、偽の AWS キーと
config.py 内にハードコードされたパスワード、USER の指定がない
Dockerfile、コミット済みの .env が含まれています。3 つすべての検出器が
検出するはずです。
出力形式
最上位のキーは、scanner、version、target、commit、scanned_at、summary、
findings、manifest_hash、errors(何らかの処理が低下した場合のみ存在)です。
manifest_hash は、{findings, target, commit} の正規化済み(キーをソートし、コンパクトにした)
JSON の sha256 です。OSV データが変わらない限り、同じコミットの実行間で安定します。
各検出結果には、id、category、severity、file、line、package、
ecosystem、version、vuln_ids、summary、evidence、fixed_in が含まれます。
検出結果は重大度、次にカテゴリ/ファイル/行の順でソートされ、id は
ソート後に割り当てられます(F-001…)。
トリアージ(--triage)
--triage を指定すると、出力に最上位のキーが 2 つ追加されます。生の検出結果と
manifest_hash は変更されません。
triage_summary— 件数と 1 行のheadline。依存関係のアドバイザリーはupgradeable(パッチ適用済みリリースが存在)とmonitor_only(まだパッチがない)に、 シークレットの検出はneeds_reviewとlikely_false_positiveに分類されます。triage— 検出結果のidを解釈に対応付けるマップです。dependency-vulnの場合、actionはupgrade(upgrade_toを含む)またはmonitorです。secretの場合は、 テスト/フィクスチャ/サンプル/CI のパス、翻訳カタログのパス(locales/、i18n/、…、v0.4.1)にある、 または値の形式を示すタグ(プレースホルダー、式、非 ASCII、ドット付きの名前、フォームのプレースホルダー、 サンプルキー。シークレットのセクションを参照)が付いている検出に対してlikely_false_positiveが true に設定されます。それ以外はすべてreviewに振り分けられます。configの検出結果はreviewです。
これは純粋に決定論的な優先順位付け(修正状況+パスに基づく誤検知の分類)です。 実際のソースコードで見つかったシークレットを除外することはありません。人による確認が必要なものとして フラグを付けます。生の検出結果が長い場合に、読者が手作業でトリアージする必要がないようにする機能です。
検査内容
1. dependency-vuln
解析対象のマニフェスト/ロックファイル(node_modules/、vendor/、.git/、
dist/、build/、target/、仮想環境内のファイルはスキップされます):
| ファイル | エコシステム | 備考 |
|---|---|---|
requirements*.txt | PyPI | == で固定された行のみ。マーカー/コメントは除去 |
poetry.lock、uv.lock | PyPI | TOML の [[package]] にある name/version |
Cargo.lock | crates.io | TOML の [[package]] |
package-lock.json | npm | v2/v3 の packages マップ。v1 の dependencies ツリーにフォールバック |
yarn.lock(v1 + Berry) | npm | v1 は name@range: + version "x"。Berry は "name@npm:range": + version: x(workspace:/patch:/portal:/link: のエントリはスキップ、v0.4。複数の @ を含む patch キーの修正は v0.4.2) |
pnpm-lock.yaml | npm | packages: のキー /[email protected] または [email protected] |
go.mod | Go | require のビルドリスト(直接依存+// indirect)。go.sum より優先(v0.4) |
go.sum | Go | 隣に go.mod がない場合のみ(go.sum には置き換えられたバージョンも含まれます)。/go.mod サフィックスは除去 |
Gemfile.lock | RubyGems | specs: セクションの name (1.2.3) |
パッケージは (ecosystem, name, version) で重複を除去し、500 件ずつに分けて
POST https://api.osv.dev/v1/querybatch に送信されます。返された各脆弱性 ID について、
重大度と修正済みバージョンを取得するため、GET https://api.osv.dev/v1/vulns/{id} から
取得します(実行ごとにメモリ内でキャッシュ)。
重大度は、存在する場合は database_specific.severity(CRITICAL/HIGH/MODERATE/LOW)を使用します。
存在しない場合は、severity リストの数値 CVSS スコアを使用し、≥9 は critical、≥7 は high、
≥4 は medium、それ未満は low に対応付けます。どちらも利用できない場合は unknown です。
パッケージの検出結果には、該当する脆弱性のうち最も高い重大度と、fixed_in バージョンの和集合が設定されます。
HTTP のタイムアウトは呼び出しごとに 20 秒です。失敗はすべて最上位の errors
リストに追加され、スキャンは続行されます。
2. secret
1 MiB 以下のテキストファイルを正規表現でスキャンします。バイナリファイル(null バイトを含むファイル)、.git/、
node_modules/、vendor/、dist/、build/、ロックファイル、*.min.js、および一般的な
バイナリ/画像拡張子はスキップされます。証拠は常に先頭 4 文字に … を付けた形に編集されます。
| パターン | 重大度 |
|---|---|
AKIA[0-9A-Z]{16}(AWS アクセスキー ID) | 高 |
gh[pousr]_[A-Za-z0-9]{36,} | 高 |
github_pat_[A-Za-z0-9_]{80,} | 高 |
xox[baprs]-[0-9A-Za-z-]{10,}(Slack) | 高 |
sk_live_[0-9a-zA-Z]{24,}(Stripe の本番用) | 重大 |
AIza[0-9A-Za-z_-]{35}(Google API キー) | 中 |
-----BEGIN … PRIVATE KEY----- | 重大 |
一般的な key/secret/password/token = "…16+ chars" | 中 |
一般的な代入ルールは、値が
example|changeme|your[_-]|xxx|dummy|placeholder|<|${ に一致する場合、重大度が低に引き下げられ、証拠に
(placeholder?) が付けられます。
値の形状に関するヒント(v0.4.1)。 2026-10-08 のデータセットでは、パスルールを通過したシークレット検出のほとんどが
実際には認証情報ではないことが示されました。そのため、証拠に以下のタグが付くようになりました。また、値が認証情報の形状でない場合は
重大度が低に引き下げられます。--triage は同じタグを誤検知の可能性が高いものとして分類します。
| タグ | 形状 |
|---|---|
(expression?) | テンプレート/環境変数参照:={{$credentials.x}}、${VAR}、$VAR、$__env{…}、{env:…}、#{…}、%{…}、<%…、var(--…) |
(non-ascii?) | ASCII 以外のテキストを含む(翻訳済みの UI テキスト、•••• のマスクなど)。認証情報は ASCII です |
(dotted-name?) | 数字を含まないドット区切り識別子(entity.other.inherited-class、grafana.someFlagToken、ホスト名など) |
(word-like?) | 数字を含まず、文字、アンダースコア、ハイフンのみ(ATTR_TOKEN = "long_lived_access_token"、API フィールド名、ヘッダー名など)。ランダムな認証情報には数字が含まれます |
(form-placeholder?) | フォームの placeholder= 属性内に一致箇所がある |
(example-key?) | 固定パターンへの一致が、文書化された例(AKIAIOSFODNN7EXAMPLE、GitHub のドキュメントにある ghp_…)または xxxx…/0000…/**** のマスクされた値である |
ヒントによって検出結果が削除されることはありません。一致箇所はタグ付きで findings に残ります。また、実際に使われている認証情報のように見える値(数字、大文字と小文字の混在、bcrypt の $2b$… ハッシュ、JWT)は元の重大度を維持し、review に振り分けられます。word-like? による既知の問題は、数字を含まない辞書由来のパスワード("correcthorsebatterystaple")が低としてタグ付けされることです。それでも一覧には表示されます。テストパスルールも v0.4.1 で拡張され、__fixtures__、__mocks__、testutils/、test-utils/、snapshots/、testUtils.* が追加されました。
3. config
.env/.env.*が、少なくとも 1 行のKEY=valueを含む状態でコミットされている — 高。Dockerfile(またはDockerfile.*)にUSER命令がない — 低、「root として実行」。DockerfileにADD http(s)://…がある — 低。docker-compose*.yml/compose.ymlにprivileged: trueが含まれている — 中。.github/workflows/*.y(a)mlでpull_request_targetおよびactions/checkoutおよび${{ github.event.pull_request.headが使用されている — 高、 「pwn リクエストパターン」。.npmrc/.pypircに_authToken=またはpassword行が含まれている — 高。
上記の設定チェックはすべて実装されています。
制限事項
- 決定論的な処理のみです。 正規表現/パーサーによるマッチングと OSV の照会のみを行います。LLM、到達可能性解析、汚染追跡は行いません。
- 誤検知のレビューは行いません。 テスト用フィクスチャ、ドキュメントの例、ローテーション済み/失効済みの認証情報も報告されます。ヒューリスティックなフィルターは、上記のパスルールと値の形式に関するヒント(v0.4.1)のみです。テスト対象外のパスに、実際の認証情報が妥当な形式でコミットされている場合、除外されることはありません。
- Git 履歴はスキャンしません。 チェックアウト済みの作業ツリーのみを調査するため(URL の対象は
--depth 1でクローンします)、後のコミットで削除されていても、履歴に残っているシークレットは検出されません。 - 推移的な依存関係の解決には、ロックファイルに記録されている内容のみを使用します。バージョンが固定されていない
requirements.txtの行(>=、~=、バージョン指定なし)はすべて無視します。 - Go では、
go.modのrequireセット(直接依存と間接依存)をビルドリストとして照会します。go.sumは隣接する場所にgo.modがない場合にのみ読み取ります。go.sumには以前のモジュールバージョンも記録されるためです(v0.4 — 2026-10-08 のデータセットでは、go.sumの検出の 99% がgo.modに含まれていませんでした)。呼び出しグラフの到達可能性は調べません。その調査にはgovulncheckを使用してください。 - Yarn v1 と Yarn Berry(v2 以降)のロックファイルを解析します(Berry は v0.4 から対応。workspace/patch/portal のエントリーはスキップします)。
composer.lock、Maven/Gradle、NuGet には対応していません。 summary.lockfiles_parsedには実際に読み取ったファイルが一覧表示されます。読み取ったファイルがない場合は、summary.notesにその旨が示されます。ゼロは「問題なし」を意味しません。テスト/フィクスチャ/例/ベンチマークのパスにあるロックファイルで見つかった依存関係は、--triageによって優先度の低いscaffoldとして分類されます。フィクスチャと配布対象の両方のロックファイルに記載されたパッケージは、配布対象のロックファイルに帰属します。- CVSS のない GHSA エントリーでは OSV の重大度が記載されていないことが多く、
unknownになります。 - シークレットの検出は行単位です。
BEGIN … PRIVATE KEYヘッダーを除き、複数行にわたるエンコード済みのデータは検出されません。
データセット
公開リポジトリ群を対象にこのスキャナーを実行した結果を、固定したコミットおよび再現用スクリプトとともに datasets/ に掲載しています。
2026-10-08-popular-oss— npm、PyPI、Go、crates.io、RubyGems の人気リポジトリ 25 件を対象としています。生の集計で誤る点(go.sumの幽霊エントリー、フィクスチャのロックファイル、不明な重大度、シークレット正規表現のノイズ)と、そこから導かれたスキャナーの修正内容を説明します。
このスキャナーで対応しきれないこと
有料プランでは、パターンマッチングでは見つけられない問題(認証やインジェクションの不備、ロジックバグ、競合状態)を再現する、3 パスの AI レビューを提供します。約 3 万行までのリポジトリは $49 です:https://project-feldspar.com/。
実際のオープンソースプロジェクトを対象としたサンプルレポートは、audits リポジトリにあります。
ライセンス
MIT。Copyright (c) 2026 Project Feldspar。有料プランの決済は L3Digital LLC d/b/a Project Feldspar が処理します。このリポジトリの記載内容は、L3Digital LLC を代表するものではありません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。