
コミュニティのための公開パッケージスキャナー
驚くほどシンプルなDockerファーストのnpmサプライチェーンスキャナー。1つのcomposeファイルで以下が実行されます:
これはコンテナ専用エディションです。このプロジェクトはEC2、SQS、RDSを使用してスケールするように構築できます。ツールセットにはそのための設定のほとんどが含まれています。
scan.yml による設定可能なルール(許可リスト、しきい値、YARA)scan_runs)がすぐに使える~/.aws を使用)docker-compose.yml – サービス: db、enumerator、fetcher、analyzer、dashboard、init-dbenumerator/ – NDJSONキューを構築するNodeワーカーfetcher/ – tarballをダウンロードするNodeワーカー(有効な場合はS3へアップロード)analyzer/ – Python静的アナライザー(オプションのインラインYARA付き)dashboard/ – Streamlitアプリ(ポート8501)infra/migrations.sql – コアDBスキーマ(packages、versions、findings、scores、indexes)infra/20251106_scan_runs.sql – スキャン履歴テーブルscan.yml – 解析設定(rules、scoring、allowlists、YARA)scripts/run_pipeline.sh – enumerate → fetch → analyze を実行scripts/init_db.sh – DBスキーマを初期化scripts/test_setup.sh – セットアップの自動検証SCANNING_GUIDE.md – 詳細なスキャン戦略と例前提条件: Compose v2 を備えた Docker Desktop(またはエンジン)。
curl -fsSL https://raw.githubusercontent.com/MHaggis/Package-Inferno/main/install.sh | bash
リポジトリを ~/package-inferno にクローンし、開始するための手順を表示します。
GitHub Container Registryからビルド済みコンテナをプルして実行します:
# Clone the repo (for config files and scripts)
git clone https://github.com/MHaggis/Package-Inferno.git
cd Package-Inferno
# Run with pre-built images
docker compose -f docker-compose.ghcr.yml up -d db
./scripts/init_db.sh
SEEDS="lodash,express" docker compose -f docker-compose.ghcr.yml run --rm enumerator
docker compose -f docker-compose.ghcr.yml run --rm fetcher
docker compose -f docker-compose.ghcr.yml run --rm analyzer
利用可能なイメージ:
ghcr.io/mhaggis/package-inferno/enumerator:mainghcr.io/mhaggis/package-inferno/fetcher:mainghcr.io/mhaggis/package-inferno/analyzer:mainインストールを検証するためにテストスクリプトを実行します:
./scripts/test_setup.sh
これにより:
docker compose up -d db
./scripts/init_db.sh
./scripts/run_pipeline.sh
docker compose up -d dashboard
# open http://localhost:8501
DBが有効な場合、検出結果は ./out/findings/*.findings.json と findings テーブルに保存されます。
PackageInfernoは、目的に応じて複数のスキャン戦略をサポートしています:
| モード | ユースケース | 速度 | カバレッジ | コマンド |
|---|---|---|---|---|
| 特定シード | 既知パッケージのテスト/調査 | 最速 | 対象を絞る | SEEDS="pkg1,pkg2" |
| 小規模バッチ | セットアップの検証、サンプルスキャン | 高速 | 10〜100パッケージ | MAX_CHUNKS=2 CHUNK_LIMIT=10 |
| 全レジストリ | 包括的なサプライチェーン監査 | 数時間〜数日 | 200万+パッケージ | MAX_CHUNKS=0 CHUNK_LIMIT=100 |
| 変更フィード | 新規リリースの監視(自動的に含まれる) | リアルタイム | 最近の更新 | 組み込み |
解析したい特定パッケージを対象にします:
# Single command with seeds
export SEEDS="lodash,express,axios"
./scripts/run_pipeline.sh
# Or from a file
echo -e "react\nvue\nangular" > packages.txt
export SEEDS_FILE=packages.txt
./scripts/run_pipeline.sh
最初にテストした方法: クイック検証には SEEDS="is-odd,is-even" を使用しました。
npmレジストリからページング処理でパッケージをスキャンします:
# Clean previous runs
rm -rf downloads/* out/*
# Scan 2 pages of 10 packages each (20 packages)
export MAX_CHUNKS=2 # Number of pages
export CHUNK_LIMIT=10 # Packages per page
unset SEEDS # Important: disable seeds mode
# Run individual steps for better visibility
docker compose run --rm enumerator # Discovers and queues
docker compose run --rm fetcher # Downloads tarballs
docker compose run --rm analyzer # Scans for threats
出力例:
config: chunkLimit=10, maxChunks=2
checking recent changes feed...
changes feed: enqueued 2 new versions
enumerating via _all_docs (fresh scan)
page 1/2 count: 10
page 2/2 count: 10
done, enqueued 22 (22 new versions)
npmレジストリ全体をスキャンします:
export MAX_CHUNKS=0 # 0 = unbounded
export CHUNK_LIMIT=100 # Larger batches for efficiency
./scripts/run_pipeline.sh
警告: これは数時間から数日間実行され、数十万のパッケージをスキャンします。ディスク容量とデータベースサイズを監視してください。
Enumerator はカーソル位置を ./out/enumerator_state.json に保存します:
{
"last_seq": "0",
"last_startkey": "package-name",
"last_run": "2025-11-23T19:24:49.123Z",
"last_processed": 22,
"last_new": 22
}
パイプラインを再実行するだけで、最後のカーソルから再開されます:
./scripts/run_pipeline.sh # Automatically resumes
新しいスキャンを強制するには:
rm -f out/enumerator_state.json
./scripts/run_pipeline.sh
22パッケージの2ページスキャンで、PackageInfernoが検出したものは次のとおりです:
-- Top suspicious packages by score
SELECT p.name, s.score, s.label, COUNT(f.id) as findings
FROM packages p
JOIN versions v ON p.id = v.package_id
JOIN scores s ON v.id = s.version_id
LEFT JOIN findings f ON v.id = f.version_id
GROUP BY p.name, s.score, s.label
ORDER BY s.score DESC;
-- Results:
name | score | label | findings
-----------------------+-------+------------+----------
rendition | 606 | malicious | 153
vs-deploy | 454 | malicious | 119
--123hoodmane-pyodide | 213 | malicious | 46
rendition がこれほど疑わしい理由:
url_outside_allowlist - 許可リスト外のドメインsuspicious_pattern - シェル/evalパターンadvanced_obfuscation - 16進エンコード、XOR、文字列配列big_base64_blob - 大きなエンコードペイロードurl_in_code - 埋め込みURLスコアリングシステム(scan.yml で設定)はこれらの検出結果を集計して、リスクスコアとラベル(clean、suspicious、または malicious)を生成します。
docker compose up -d dashboard 実行後、 http://localhost:8501 を開きます
機能:
カスタム分析のための直接SQLアクセス:
# Connect to database
docker exec -it pi-postgres psql -U piuser -d packageinferno
便利なクエリ:
-- Packages with credential theft attempts
SELECT DISTINCT p.name, v.version, s.score
FROM packages p
JOIN versions v ON p.id = v.package_id
JOIN findings f ON v.id = f.version_id
JOIN scores s ON v.id = s.version_id
WHERE f.rule = 'env_snoop'
ORDER BY s.score DESC;
-- All C2/webhook destinations found
SELECT p.name, f.details->>'endpoints' as c2_endpoints
FROM packages p
JOIN versions v ON p.id = v.package_id
JOIN findings f ON v.id = f.version_id
WHERE f.rule = 'c2_webhook';
-- Typosquatting attempts
SELECT
p.name,
f.details->>'target_package' as impersonating,
f.details->>'similarity' as similarity_pct,
f.details->>'typosquat_type' as attack_type
FROM packages p
JOIN versions v ON p.id = v.package_id
JOIN findings f ON v.id = f.version_id
WHERE f.rule = 'typosquat_detected'
ORDER BY (f.details->>'similarity')::float DESC;
-- Packages with native binaries
SELECT p.name, f.details->>'path' as binary_path
FROM packages p
JOIN versions v ON p.id = v.package_id
JOIN findings f ON v.id = f.version_id
WHERE f.rule = 'native_binary_present';
検出結果は ./out/findings/ 配下に構造化JSONとしても保存されます:
# View findings for a specific package
cat out/findings/[email protected] | jq .
# Count findings by severity
jq -r '.findings[].severity' out/findings/*.findings.json | sort | uniq -c