@lateos/npm-scan 0.15.5 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +11 -2
- package/README.fr.md +11 -2
- package/README.ja.md +11 -2
- package/README.md +28 -2
- package/README.zh.md +11 -2
- package/backend/detectors/cve-2026-48710-badhost/codePattern.js +99 -0
- package/backend/detectors/cve-2026-48710-badhost/findings.js +105 -0
- package/backend/detectors/cve-2026-48710-badhost/index.js +15 -0
- package/backend/detectors/cve-2026-48710-badhost/manifest.js +305 -0
- package/backend/detectors/cve-2026-48710-badhost/transitive.js +189 -0
- package/backend/detectors/index.js +6 -0
- package/backend/detectors/node-ipc-compromise/d1-version-blocklist.js +24 -0
- package/backend/detectors/node-ipc-compromise/d10-unauthorized-publisher.js +19 -0
- package/backend/detectors/node-ipc-compromise/d11-blast-radius.js +40 -0
- package/backend/detectors/node-ipc-compromise/d2-tarball-hash.js +31 -0
- package/backend/detectors/node-ipc-compromise/d3-cjs-payload-injection.js +73 -0
- package/backend/detectors/node-ipc-compromise/d4-injected-payload-hash.js +37 -0
- package/backend/detectors/node-ipc-compromise/d5-dns-c2-pattern.js +49 -0
- package/backend/detectors/node-ipc-compromise/d6-bootstrap-resolver.js +40 -0
- package/backend/detectors/node-ipc-compromise/d7-dns-txt-exfil.js +42 -0
- package/backend/detectors/node-ipc-compromise/d8-runtime-trigger.js +27 -0
- package/backend/detectors/node-ipc-compromise/d9-temp-artifact.js +20 -0
- package/backend/detectors/node-ipc-compromise/index.js +93 -0
- package/backend/detectors/node-ipc-compromise/iocs.json +59 -0
- package/backend/detectors/trapdoor/d1-campaign-marker.js +20 -0
- package/backend/detectors/trapdoor/d2-payload-fingerprint.js +22 -0
- package/backend/detectors/trapdoor/d3-publisher-blocklist.js +10 -0
- package/backend/detectors/trapdoor/d4-gists-exfil.js +34 -0
- package/backend/detectors/trapdoor/d5-ai-poisoning.js +35 -0
- package/backend/detectors/trapdoor/d6-lure-name.js +42 -0
- package/backend/detectors/trapdoor/d7-crypto-primitives.js +22 -0
- package/backend/detectors/trapdoor/d8-xor-key.js +15 -0
- package/backend/detectors/trapdoor/d9-cred-validation.js +32 -0
- package/backend/detectors/trapdoor/index.js +77 -0
- package/backend/detectors/trapdoor/iocs.json +51 -0
- package/package.json +1 -1
package/README.de.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@lateos/npm-scan)
|
|
10
10
|
[](LICENSING.md)
|
|
11
11
|
[](package.json)
|
|
12
|
-
[](https://github.com/lateos-ai/npm-scan)
|
|
13
13
|
[](https://github.com/lateos-ai/npm-scan)
|
|
14
14
|
[](https://hub.docker.com/r/lateos/npm-scan)
|
|
15
15
|
[](https://github.com/lateos-ai/npm-scan/actions/workflows/publish.yml)
|
|
@@ -227,6 +227,9 @@ npm-scan report --pdf # alle Scans (Premium)
|
|
|
227
227
|
| **ATK-009** | Bedingte/schlafende Auslöser (CI-Erkennung, zeitbasiert) | Verhaltensbasiert | 🔴 hoch | SR-9.2 |
|
|
228
228
|
| **ATK-010** | Sandbox-Evasion / Anti-Analyse | Verhaltensbasiert | 🟠 mittel | SR-10.3 |
|
|
229
229
|
| **ATK-011** | Transitive Verbreitung (wurmartige laterale Ausbreitung) | Verhaltensbasiert | 🔴 hoch | SR-11.4 |
|
|
230
|
+
| **CVE-2026-48710** | BadHost — Starlette Authentifizierungs-Bypass via Host-Header-Injection (CVE-2026-48710, CVSS 7.0). Python-Abhängigkeitsversionserkennung (requirements.txt, pyproject.toml, poetry.lock, Pipfile, setup.py/cfg), transitive Heuristik (15 bekannte Downstream-Pakete: fastapi, vllm, litellm, MCP-Server, etc.), statische Code-Pattern-Analyse für gefährliche `request.url.path`-Nutzung in Auth/Middleware-Kontexten mit `request.scope["path"]`-Unterdrückung | Statisch + Registry | 🔴 hoch / 🟠 mittel / ℹ️ info | SR-3.1, SR-5.3 |
|
|
231
|
+
| **TRAPDOOR** | TrapDoor plattformübergreifende Angriffskampagne — Kampagnenmarker P-2024-001, trap-core.js-Payload-Fingerprint, Publisher-Blocklist asdxzxc, Gist-basierter Credential-Exfil, KI-Kontextvergiftung (Zero-Width-Unicode), Crypto/DeFi-Locknamen, Fernet+ECDH-Verschlüsselung, XOR-Key cargo-build-helper-2026, STS/GitHub-API-Validierung | Statisch + Registry | 🟠 mittel / 🔴 hoch / ⚫ kritisch | SR-3.1, SR-5.3, SR-7.5 |
|
|
232
|
+
| **NODE_IPC_COMPROMISE** | node-ipc Supply-Chain-Kompromittierung (14. Mai 2026) — Versions-Blocklist (9.1.6/9.2.3/12.0.1) mit sicheren Pins, Tarball-SHA-256-Verifikation, CJS-Payload-IIFE-Injektion, DNS-over-nicht-Standard-Port-C2, Bootstrap-Resolver sh.azurestaticprovider.net, DNS-TXT-Exfiltrationszone bt.node.js, setImmediate()-Laufzeitauslöser, ~/nt-*/ Staging-Artefakte, unbefugter Publisher atiertant, Lockfile-Blastradius | Statisch + Registry | ⚫ kritisch | SR-3.1, SR-5.3, SR-7.5 |
|
|
230
233
|
|
|
231
234
|
> **Wie ausweichende Angriffe erkannt werden:** ATK-009 erkennt Pakete, die `process.env.CI` prüfen, Hostnamen sondieren oder zeitbasierte Aktivierung verwenden. ATK-010 markiert `debugger`-Anweisungen, `os.hostname()`-Sonden und Umgebungs-Fingerprinting. ATK-011 verfolgt Peer-Abhängigkeitsgraphen, um wurmartige Verbreitungsmuster zu erkennen.
|
|
232
235
|
> Vollständige Dokumentation der Ausweichfläche und PoC-Beispiele finden Sie in [`docs/attack-taxonomy.md`](docs/attack-taxonomy.md).
|
|
@@ -548,7 +551,7 @@ Siehe den obigen [Docker-Schnellstart-Abschnitt](#-lateosnpm-scan-überall-mit-d
|
|
|
548
551
|
|
|
549
552
|
### Kostenlose Stufe (ausgeliefert)
|
|
550
553
|
|
|
551
|
-
- Alle 11 ATK-Detektoren (statisch + verhaltensbasiert)
|
|
554
|
+
- Alle 11 ATK-Detektoren (statisch + verhaltensbasiert) + **MEGALODON** + **HF_IMPERSONATION** + **MINI_SHAI_HULUD** + **VSIX_SCAN** + **CVE-2026-48710 (BadHost)** + **TRAPDOOR** (9 Regeln) + **NODE_IPC_COMPROMISE** (11 Regeln)
|
|
552
555
|
- SBOM-Ausgabe (CycloneDX + SPDX)
|
|
553
556
|
- HTML-, Text- und Compliance-Berichte (NIST + EU CRA)
|
|
554
557
|
- Policy-as-Code-Engine (YAML)
|
|
@@ -611,6 +614,12 @@ node --test test/detectors-corpus.test.js
|
|
|
611
614
|
- `test/fetch.test.js` — Tarball-Extraktion, Bereinigung temporärer Verzeichnisse
|
|
612
615
|
- `test/policy-edge-cases.test.js` — Grenzfälle bei Unterdrückung, Überschreibung, Ladevalidierung
|
|
613
616
|
- `test/report-snapshots.test.js` — HTML/Text/CRA/PDF-Format-Assertions
|
|
617
|
+
- `test/cve-2026-48710-badhost/manifest.test.js` — 13 Python-Manifest-Parsing-Tests (requirements.txt, pyproject.toml, poetry.lock, Version-Grenzfälle)
|
|
618
|
+
- `test/cve-2026-48710-badhost/transitive.test.js` — 7 transitive Abhängigkeitstests (Tier 1/2, fastapi-Version-Gating, Pin-Unterdrückung)
|
|
619
|
+
- `test/cve-2026-48710-badhost/codePattern.test.js` — 6 statische Code-Pattern-Tests (Auth-Kontext, INFO-Durchgriff, Scope-Unterdrückung)
|
|
620
|
+
- `test/cve-2026-48710-badhost/integration.test.js` — 4 Integrationstests (End-to-End-Composite-Findings, sauberes Projekt, keine Python-Dateien)
|
|
621
|
+
- `test/trapdoor.test.js` — 40 TrapDoor-Kampagnenerkennungstests (D1–D9: Kampagnenmarker, Payload-Fingerprint, Publisher-Blocklist, Gist-Exfil, KI-Vergiftung, Lockname, Krypto-Primitive, XOR-Key, Credential-Validierung)
|
|
622
|
+
- `test/node-ipc.test.js` — 37 node-ipc-Kompromittierungstests (D1–D11: Versions-Blocklist, Tarball-Hash, CJS-Injektion, Payload-Hash, DNS-C2-Muster, Bootstrap-Resolver, DNS-TXT-Exfil, Laufzeitauslöser, Temp-Artefakte, unbefugter Publisher, Blastradius)
|
|
614
623
|
- `test/cli.test.js` — Commander-Integrationstests (Hilfe, Version, Scan, Bericht, Fehlerbehandlung)
|
|
615
624
|
|
|
616
625
|
### Hilfe benötigt?
|
package/README.fr.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@lateos/npm-scan)
|
|
10
10
|
[](LICENSING.md)
|
|
11
11
|
[](package.json)
|
|
12
|
-
[](https://github.com/lateos-ai/npm-scan)
|
|
13
13
|
[](https://github.com/lateos-ai/npm-scan)
|
|
14
14
|
[](https://hub.docker.com/r/lateos/npm-scan)
|
|
15
15
|
[](https://github.com/lateos-ai/npm-scan/actions/workflows/publish.yml)
|
|
@@ -227,6 +227,9 @@ npm-scan report --pdf # tous les scans (premium)
|
|
|
227
227
|
| **ATK-009** | Déclencheurs conditionnels/dormants (détection CI, temporel) | Comportementale | 🔴 élevée | SR-9.2 |
|
|
228
228
|
| **ATK-010** | Contournement de sandbox / anti-analyse | Comportementale | 🟠 moyenne | SR-10.3 |
|
|
229
229
|
| **ATK-011** | Propagation transitive (dissémination latérale de type ver) | Comportementale | 🔴 élevée | SR-11.4 |
|
|
230
|
+
| **CVE-2026-48710** | BadHost — contournement d'authentification Starlette par injection d'en-tête Host (CVE-2026-48710, CVSS 7.0). Détection de version de dépendance Python (requirements.txt, pyproject.toml, poetry.lock, Pipfile, setup.py/cfg), heuristique transitive (15 paquets aval connus : fastapi, vllm, litellm, serveurs MCP, etc.), analyse statique de code pour `request.url.path` dangereux en contexte auth/middleware avec suppression par `request.scope["path"]` | Statique + Registre | 🔴 élevée / 🟠 moyenne / ℹ️ info | SR-3.1, SR-5.3 |
|
|
231
|
+
| **TRAPDOOR** | Campagne d'attaque multi-écosystème TrapDoor — marqueur de campagne P-2024-001, empreinte de charge utile trap-core.js, liste noire d'éditeur asdxzxc, exfiltration d'identifiants via Gist, empoisonnement de contexte IA (Unicode largeur nulle), noms leurres crypto/DeFi, chiffrement Fernet+ECDH, clé XOR cargo-build-helper-2026, validation d'identifiants STS/API GitHub | Statique + Registre | 🟠 moyenne / 🔴 élevée / ⚫ critique | SR-3.1, SR-5.3, SR-7.5 |
|
|
232
|
+
| **NODE_IPC_COMPROMISE** | Compromission de la chaîne d'approvisionnement node-ipc (14 mai 2026) — liste noire de versions (9.1.6/9.2.3/12.0.1) avec épingle de sécurité, vérification SHA-256 du tarball, injection IIFE de charge utile CJS, DNS sur port non standard, résolveur d'amorçage sh.azurestaticprovider.net, zone d'exfiltration DNS TXT bt.node.js, déclencheur d'exécution setImmediate(), artefacts de staging ~/nt-*/, éditeur non autorisé atiertant, détection du rayon d'impact dans les lockfiles avec recommandations d'épingle | Statique + Registre | ⚫ critique | SR-3.1, SR-5.3, SR-7.5 |
|
|
230
233
|
|
|
231
234
|
> **Comment les attaques furtives sont détectées :** ATK-009 détecte les paquets qui vérifient `process.env.CI`, sondent les noms d'hôte ou utilisent une activation temporelle. ATK-009 signale les instructions `debugger`, les sondes `os.hostname()` et l'empreinte environnementale. ATK-011 trace les graphes de dépendances peer pour détecter les schémas de propagation de type ver.
|
|
232
235
|
> Voir [`docs/attack-taxonomy.md`](docs/attack-taxonomy.md) pour la documentation complète de la surface d'évasion et des exemples de PoC.
|
|
@@ -548,7 +551,7 @@ Voir la [section Démarrage rapide Docker](#-exécutez-lateosnpm-scan-partout-av
|
|
|
548
551
|
|
|
549
552
|
### Niveau gratuit (livré)
|
|
550
553
|
|
|
551
|
-
- Les 11 détecteurs ATK (statique + comportemental)
|
|
554
|
+
- Les 11 détecteurs ATK (statique + comportemental) + **MEGALODON** + **HF_IMPERSONATION** + **MINI_SHAI_HULUD** + **VSIX_SCAN** + **CVE-2026-48710 (BadHost)** + **TRAPDOOR** (9 règles) + **NODE_IPC_COMPROMISE** (11 règles)
|
|
552
555
|
- Sortie SBOM (CycloneDX + SPDX)
|
|
553
556
|
- Rapports HTML, texte et conformité (NIST + EU CRA)
|
|
554
557
|
- Moteur de politique en tant que code (YAML)
|
|
@@ -611,6 +614,12 @@ node --test test/detectors-corpus.test.js
|
|
|
611
614
|
- `test/fetch.test.js` — extraction de tarball, nettoyage de répertoire temporaire
|
|
612
615
|
- `test/policy-edge-cases.test.js` — cas limites dans la suppression, la surcharge, la validation de chargement
|
|
613
616
|
- `test/report-snapshots.test.js` — assertions de format HTML/texte/CRA/PDF
|
|
617
|
+
- `test/cve-2026-48710-badhost/manifest.test.js` — 13 tests d'analyse de manifeste Python (requirements.txt, pyproject.toml, poetry.lock, cas limites de version)
|
|
618
|
+
- `test/cve-2026-48710-badhost/transitive.test.js` — 7 tests de dépendances transitives (Tier 1/2, contrôle de version fastapi, suppression par épinglage)
|
|
619
|
+
- `test/cve-2026-48710-badhost/codePattern.test.js` — 6 tests de motifs de code statiques (contexte auth, passage INFO, suppression scope)
|
|
620
|
+
- `test/cve-2026-48710-badhost/integration.test.js` — 4 tests d'intégration (résultats composites de bout en bout, projet propre, pas de fichiers Python)
|
|
621
|
+
- `test/trapdoor.test.js` — 40 tests de détection de la campagne TrapDoor (D1–D9 : marqueur de campagne, empreinte de charge utile, liste noire d'éditeur, exfiltration Gist, empoisonnement IA, nom leurre, primitives cryptographiques, clé XOR, validation d'identifiants)
|
|
622
|
+
- `test/node-ipc.test.js` — 37 tests de détection de compromission node-ipc (D1–D11 : liste noire de versions, hachage tarball, injection CJS, hachage de charge utile, motif DNS C2, résolveur d'amorçage, exfiltration DNS TXT, déclencheur d'exécution, artefacts temporaires, éditeur non autorisé, rayon d'impact)
|
|
614
623
|
- `test/cli.test.js` — tests d'intégration commander (aide, version, scan, rapport, gestion d'erreurs)
|
|
615
624
|
|
|
616
625
|
### Besoin d'aide ?
|
package/README.ja.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@lateos/npm-scan)
|
|
10
10
|
[](LICENSING.md)
|
|
11
11
|
[](package.json)
|
|
12
|
-
[](https://github.com/lateos-ai/npm-scan)
|
|
13
13
|
[](https://github.com/lateos-ai/npm-scan)
|
|
14
14
|
[](https://hub.docker.com/r/lateos/npm-scan)
|
|
15
15
|
[](https://github.com/lateos-ai/npm-scan/actions/workflows/publish.yml)
|
|
@@ -223,6 +223,9 @@ npm-scan report --pdf # すべてのスキャン(プレミアム
|
|
|
223
223
|
| **ATK-009** | 条件付き/潜伏トリガー(CI検出、時間ベース) | 行動 | 🔴 高 | SR-9.2 |
|
|
224
224
|
| **ATK-010** | サンドボックス回避/アンチ解析 | 行動 | 🟠 中 | SR-10.3 |
|
|
225
225
|
| **ATK-011** | 推移的伝播(ワーム型横方向拡散) | 行動 | 🔴 高 | SR-11.4 |
|
|
226
|
+
| **CVE-2026-48710** | BadHost — Starlette Host ヘッダーインジェクション認証バイパス (CVE-2026-48710, CVSS 7.0)。Python 依存関係バージョン検出 (requirements.txt, pyproject.toml, poetry.lock, Pipfile, setup.py/cfg)、推移的ヒューリスティック (15 の既知ダウンストリームパッケージ:fastapi, vllm, litellm, MCP サーバー等)、auth/middleware コンテキストでの危険な `request.url.path` 使用の静的コードパターンスキャン、`request.scope["path"]` による抑制対応 | 静的 + レジストリ | 🔴 高 / 🟠 中 / ℹ️ 情報 | SR-3.1, SR-5.3 |
|
|
227
|
+
| **TRAPDOOR** | TrapDoor クロスエコシステム攻撃キャンペーン — キャンペーンマーカー P-2024-001、trap-core.js ペイロードフィンガープリント、パブリッシャーブロックリスト asdxzxc、Gist ベースの認証情報流出、AI コンテキストポイズニング(ゼロ幅 Unicode)、暗号資産/DeFi ルアー名、Fernet+ECDH 暗号化、XOR キー cargo-build-helper-2026、STS/GitHub API 認証情報検証 | 静的 + レジストリ | 🟠 中 / 🔴 高 / ⚫ クリティカル | SR-3.1, SR-5.3, SR-7.5 |
|
|
228
|
+
| **NODE_IPC_COMPROMISE** | node-ipc サプライチェーン侵害(2026年5月14日)— バージョンブロックリスト (9.1.6/9.2.3/12.0.1) と安全な固定、tarball SHA-256 検証、CJS ペイロード IIFE インジェクション、非標準ポート DNS C2 パターン、ブートストラップリゾルバー sh.azurestaticprovider.net、DNS TXT 流出ゾーン bt.node.js、setImmediate() ランタイムトリガー、~/nt-*/ ステージングアーティファクト、未承認パブリッシャー atiertant、ロックファイル影響範囲検出と安全な固定推奨 | 静的 + レジストリ | ⚫ クリティカル | SR-3.1, SR-5.3, SR-7.5 |
|
|
226
229
|
|
|
227
230
|
> **回避型攻撃の捕捉方法:** ATK-009は`process.env.CI`をチェックする、ホスト名をプローブする、または時間ベースのアクティベーションを使用するパッケージを検出します。ATK-010は`debugger`文、`os.hostname()`プローブ、環境フィンガープリンティングをフラグ付けします。ATK-011はピア依存関係グラフをトレースしてワーム型伝播パターンを検出します。
|
|
228
231
|
> 完全な回避面のドキュメントとPoC例については、[`docs/attack-taxonomy.md`](docs/attack-taxonomy.md)を参照してください。
|
|
@@ -544,7 +547,7 @@ npm-scan report --html > report.html
|
|
|
544
547
|
|
|
545
548
|
### 無料版(出荷済み)
|
|
546
549
|
|
|
547
|
-
- 全11ATK
|
|
550
|
+
- 全11ATK検出器(静的+行動)+ **MEGALODON** + **HF_IMPERSONATION** + **MINI_SHAI_HULUD** + **VSIX_SCAN** + **CVE-2026-48710 (BadHost)** + **TRAPDOOR**(9ルール)+ **NODE_IPC_COMPROMISE**(11ルール)
|
|
548
551
|
- SBOM出力(CycloneDX + SPDX)
|
|
549
552
|
- HTML、テキスト、コンプライアンスレポート(NIST + EU CRA)
|
|
550
553
|
- ポリシー・アズ・コードエンジン(YAML)
|
|
@@ -607,6 +610,12 @@ node --test test/detectors-corpus.test.js
|
|
|
607
610
|
- `test/fetch.test.js` — tarball抽出、一時ディレクトリクリーンアップ
|
|
608
611
|
- `test/policy-edge-cases.test.js` — 抑制、上書き、ロード検証のエッジケース
|
|
609
612
|
- `test/report-snapshots.test.js` — HTML/テキスト/CRA/PDF形式のアサーション
|
|
613
|
+
- `test/cve-2026-48710-badhost/manifest.test.js` — 13のPythonマニフェスト解析テスト(requirements.txt, pyproject.toml, poetry.lock, バージョンエッジケース)
|
|
614
|
+
- `test/cve-2026-48710-badhost/transitive.test.js` — 7の推移的依存関係テスト(Tier 1/2, fastapiバージョンゲーティング, 固定抑制)
|
|
615
|
+
- `test/cve-2026-48710-badhost/codePattern.test.js` — 6の静的コードパターンテスト(authコンテキスト, INFOフォールスルー, scope抑制)
|
|
616
|
+
- `test/cve-2026-48710-badhost/integration.test.js` — 4の統合テスト(エンドツーエンド複合発見項目, クリーンプロジェクト, Pythonファイルなし)
|
|
617
|
+
- `test/trapdoor.test.js` — 40のTrapDoorキャンペーン検出テスト(D1–D9:キャンペーンマーカー、ペイロードフィンガープリント、パブリッシャーブロックリスト、Gist流出、AIポイズニング、ルアー名、暗号プリミティブ、XORキー、認証情報検証)
|
|
618
|
+
- `test/node-ipc.test.js` — 37のnode-ipc侵害検出テスト(D1–D11:バージョンブロックリスト、tarballハッシュ、CJSインジェクション、ペイロードハッシュ、DNS C2パターン、ブートストラップリゾルバー、DNS TXT流出、ランタイムトリガー、一時アーティファクト、未承認パブリッシャー、影響範囲)
|
|
610
619
|
- `test/cli.test.js` — commander統合テスト(ヘルプ、バージョン、スキャン、レポート、エラーハンドリング)
|
|
611
620
|
|
|
612
621
|
### ヘルプが必要ですか?
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@lateos/npm-scan)
|
|
4
4
|
[](LICENSING.md)
|
|
5
5
|
[](package.json)
|
|
6
|
-
[](https://github.com/lateos-ai/npm-scan)
|
|
7
7
|
[](https://github.com/lateos-ai/npm-scan)
|
|
8
8
|
[](https://hub.docker.com/r/lateos/npm-scan)
|
|
9
9
|
[](https://github.com/lateos-ai/npm-scan/actions/workflows/publish.yml)
|
|
@@ -28,6 +28,12 @@ A growing attack vector is **HuggingFace org impersonation** — packages that m
|
|
|
28
28
|
|
|
29
29
|
The **Megalodon campaign** (2026) alone compromised 5,500+ repositories via fake GitHub PRs, malicious workflow injection, and cloud credential exfiltration — all coordinated through a single actor automating the entire kill chain. **@lateos/npm-scan** now detects artifacts of this campaign out of the box.
|
|
30
30
|
|
|
31
|
+
The **TrapDoor campaign** (May 2026) spans npm, PyPI, and Crates.io — 34 malicious packages, 384+ versions attributed to a single publisher, targeting crypto, DeFi, Solana, and AI developers with Fernet + ECDH encrypted payloads, AI context poisoning via zero-width Unicode injection in `.cursorrules`/`CLAUDE.md`, and credential live-validation against AWS STS and GitHub API before exfiltration. **@lateos/npm-scan** now detects all 9 TrapDoor signals.
|
|
32
|
+
|
|
33
|
+
The **node-ipc compromise** (May 14, 2026) weaponized an expired maintainer email domain to hijack one of npm's most depended-upon packages (822K weekly downloads). Three malicious versions (9.1.6, 9.2.3, 12.0.1) delivered an 80KB credential stealer via DNS TXT tunneling — no HTTP, no postinstall hook, invisible to HTTP-layer firewalls. **@lateos/npm-scan** now detects all 11 node-ipc compromise signals.
|
|
34
|
+
|
|
35
|
+
Critical infrastructure vulnerabilities in the Python ecosystem are also in scope. The **BadHost (CVE-2026-48710)** vulnerability in Starlette < 1.0.1 enables authentication bypass via unvalidated HTTP Host header injection, affecting FastAPI, vLLM, LiteLLM, MCP servers, and any project using Starlette transitively — now detected across Python manifests, transitive dependency chains, and source code patterns in a single scan.
|
|
36
|
+
|
|
31
37
|
**npm audit** checks known CVEs. **Snyk** scans for vulnerabilities. **Socket** looks at package behavior. None of them were designed for the generation of attacks that emerged in 2025 — attacks that look benign until they reach production.
|
|
32
38
|
|
|
33
39
|
**@lateos/npm-scan** was built for this moment.
|
|
@@ -50,6 +56,9 @@ The **Megalodon campaign** (2026) alone compromised 5,500+ repositories via fake
|
|
|
50
56
|
| Worm campaign detection (Mini Shai-Hulud Wave 1–3) | ❌ | ❌ | ❌ | ✅ |
|
|
51
57
|
| HF model repo impersonation + README clone | ❌ | ❌ | ❌ | ✅ |
|
|
52
58
|
| VS Code extension supply chain scan (--vsix) | ❌ | ❌ | ❌ | ✅ |
|
|
59
|
+
| Python vulnerability detection (CVE-2026-48710 BadHost) | ❌ | ❌ | ❌ | ✅ |
|
|
60
|
+
| Cross-ecosystem attack detection (TrapDoor) | ❌ | ❌ | ❌ | ✅ |
|
|
61
|
+
| Expired-domain hijack detection (node-ipc) | ❌ | ❌ | ❌ | ✅ |
|
|
53
62
|
| Attack taxonomy (ATK series) | ❌ | ❌ | ❌ | ✅ |
|
|
54
63
|
| SBOM output (CycloneDX + SPDX) | ❌ | ✅ | ❌ | ✅ |
|
|
55
64
|
| SARIF v2.1 (GitHub Code Scanning) | ❌ | ❌ | ❌ | ✅ |
|
|
@@ -72,6 +81,9 @@ The **Megalodon campaign** (2026) alone compromised 5,500+ repositories via fake
|
|
|
72
81
|
| 🧬 | **ATK attack taxonomy** | 11 classified attack types with NIST 800-161 mappings — versioned, documented, and PR-able |
|
|
73
82
|
| 🪱 | **Worm campaign detection** | Mini Shai-Hulud — 6 sub-checks detecting burst publish, sibling compromise, SLSA attestation mismatch, publisher drift, IOC match, and token exfil across 3 waves (TanStack, AntV/atool, Nx Console) |
|
|
74
83
|
| 🧩 | **VSIX extension scanning** | `npm-scan scan --vsix nrwl.angular-console` — detects VS Code Marketplace supply chain attacks: burst publish, publisher anomaly, activation event risk, orphan commit fetch, known IOC, and exfil patterns (Nx Console 18.95.0 CVE-2026-48027) |
|
|
84
|
+
| 🐍 | **Python vulnerability detection** | CVE-2026-48710 (BadHost) — Starlette Host header injection across 6 Python manifest formats, 15 transitive downstream packages (fastapi, vllm, litellm, MCP), and static `request.url.path` code pattern analysis with `scope["path"]` suppression |
|
|
85
|
+
| 🪤 | **Cross-ecosystem attack detection** | TrapDoor — 9 sub-checks: campaign marker P-2024-001, trap-core.js payload fingerprint, publisher blocklist asdxzxc, Gist-based credential exfil, AI config zero-width Unicode poisoning, crypto/DeFi lure name heuristic, Fernet+ECDH encryption, XOR key cargo-build-helper-2026, STS/GitHub API credential validation |
|
|
86
|
+
| 📡 | **Expired-domain hijack detection** | node-ipc compromise — version blocklist (9.1.6/9.2.3/12.0.1), tarball SHA-256 verification, CJS vs ESM size anomaly with IIFE injection, DNS-over-non-standard-port C2, bootstrap resolver sh.azurestaticprovider.net, DNS TXT exfil zone bt.node.js, setImmediate() runtime trigger, ~/nt-*/ staging artifacts, unauthorized publisher atiertant, lockfile blast-radius with safe pin recommendations |
|
|
75
87
|
| 📦 | **SBOM generation** | CycloneDX 1.5 and SPDX 2.3 with findings embedded as vulnerabilities |
|
|
76
88
|
| 🔍 | **SARIF output** | GitHub Advanced Security / CodeQL compatible SARIF v2.1 — shows findings directly in Security tab |
|
|
77
89
|
| 🧾 | **Compliance reporting** | NIST SP 800-161 traceability matrix + EU Cyber Resilience Act mapping (free tier) |
|
|
@@ -281,12 +293,18 @@ npm-scan report --pdf # all scans (premium)
|
|
|
281
293
|
| **HF_IMPERSONATION** | HuggingFace org spoof detection — Jaro-Winkler similarity against 15 known-good orgs, SimHash README clone detection, artifact mismatch (`.exe`/`.dll` in model repos), postinstall escalation, new-org amplifier | Static + Network (Stage 2) | 🔴 high / ⚫ critical | SR-2.1 |
|
|
282
294
|
| **MINI_SHAI_HULUD** | Mini Shai-Hulud worm campaign — burst publish velocity (≥3 versions/30 min), co-temporal sibling compromise, SLSA attestation mismatch (sub-60s gap, first-ever, builder mismatch), publisher drift (<10 min account change), IOC match (scope/sha512/publisher from seed file), token exfil (NPM_TOKEN/.npmrc/atob patterns), Nx Console downstream detection | Static + Registry | 🔴 high / ⚫ critical | SR-3.1, SR-7.5 |
|
|
283
295
|
| **VSIX_SCAN** | VS Code extension supply chain scan — burst publish (≥2 versions/30 min, hot-pull <20 min), publisher anomaly (account substitution, new-account on high-install ext, 15-min add+publish), activation event risk (onStartupFinished→HIGH, *→CRITICAL, escalation on shell keywords), orphan commit fetch (GitHub API SHA refs, npx git URL, MCP-disguised exfil, Bun install), known IOC (extensionId/publisherAccount/commit hash from seed), exfil patterns (cred paths, DNS tunneling, AES+RSA, anti-analysis, Bun APIs) | Static + Registry | 🟠 medium / 🔴 high / ⚫ critical | SR-3.1, SR-5.3 |
|
|
296
|
+
| **CVE-2026-48710** | BadHost — Starlette authentication bypass via Host header injection (CVE-2026-48710, CVSS 7.0). Python dependency version detection (requirements.txt, pyproject.toml, poetry.lock, Pipfile, setup.py/cfg), transitive heuristic (15 known downstream packages: fastapi, vllm, litellm, MCP servers, etc.), static code pattern scan for dangerous `request.url.path` usage in auth/middleware context with `request.scope["path"]` suppression | Static + Registry | 🔴 high / 🟠 medium / ℹ️ info | SR-3.1, SR-5.3 |
|
|
297
|
+
| **TRAPDOOR** | TrapDoor cross-ecosystem attack — campaign marker P-2024-001 in files, shared payload trap-core.js filename/48,485-byte fingerprint, publisher blocklist asdxzxc, Gist-based credential exfil (ddjidd564.github.io + credential paths), AI context poisoning via zero-width Unicode in .cursorrules/CLAUDE.md, crypto/DeFi lure name heuristic (<30 days), Fernet+ECDH crypto primitives in postinstall, XOR key cargo-build-helper-2026 in lockfiles, STS/GitHub API credential validation in postinstall | Static + Registry | 🟠 medium / 🔴 high / ⚫ critical | SR-3.1, SR-5.3, SR-7.5 |
|
|
298
|
+
| **NODE_IPC_COMPROMISE** | node-ipc supply chain compromise (May 14, 2026) — version blocklist (9.1.6/9.2.3/12.0.1) with safe pins, tarball SHA-256 verification, CJS payload IIFE injection detection (CJS>ESM size differential), injected payload hash match, DNS-over-non-standard-port C2 (setServers + custom resolver), bootstrap resolver sh.azurestaticprovider.net + C2 IP 37.16.75.69, DNS TXT exfiltration zone bt.node.js, setImmediate() runtime trigger, ~/nt-*/ staging artifact detection, unauthorized publisher atiertant, lockfile blast-radius detection with pin recommendations | Static + Registry | ⚫ critical | SR-3.1, SR-5.3, SR-7.5 |
|
|
284
299
|
|
|
285
300
|
> **How evasive attacks are caught:** ATK-009 detects packages that check `process.env.CI`, probe hostnames, or use time-based activation. ATK-010 flags `debugger` statements, `os.hostname()` probes, and env fingerprinting. ATK-011 traces peer dependency graphs to detect worm-like propagation patterns.
|
|
286
301
|
> **MEGALODON** campaign detection analyzes bundled `.github/workflows/` files for C2 co-occurrence and base64 decode chains, scans tarball files for credential + outbound network patterns, detects version publish velocity spikes via npm registry metadata, and identifies publisher account drift — all without any network calls beyond the initial package fetch.
|
|
287
302
|
> **HF_IMPERSONATION** detection uses a lazy two-stage evaluation: Stage 1 scans `package.json` scripts and JS/TS sources for HuggingFace references (URLs, `from_pretrained()`, `hub.download()`) and runs Jaro-Winkler similarity against 15 known-good HF orgs — zero network. If spoofs are found, Stage 2 fetches the HF model API, computes SimHash of both READMEs for clone detection, validates artifact type consistency (e.g., `transformers` library with `.exe` files is flagged as critical), applies a new-org amplifier (<30 days), and escalates when the reference appears in a lifecycle script.
|
|
288
303
|
> **MINI_SHAI_HULUD** worm campaign detection uses a lazy two-stage evaluation: Stage 1 runs burst velocity, publisher drift, IOC, and token exfil checks (in-memory, no network). If burst triggers, Stage 2 queries npm attestation endpoints for SLSA anomalies and fetches sibling package registry metadata for co-temporal burst detection. Composite finding includes wave attribution (wave1-tanstack, wave2-antv, wave3-nx-console) and critical severity when SLSA or IOC match. NX_CONSOLE_DOWNSTREAM (D7) flags npm packages with `@nx/*` dependencies and checks for `nrwl.angular-console` in `.vscode/extensions.json`.
|
|
289
304
|
> **VSIX_SCAN** extension scanning wraps both VS Code Marketplace and Open VSX registries with rate-limited (10 req/min), cached (5 min TTL) API clients. All 6 detectors run asynchronously and aggregate into a single composite `VSIX_SCAN` finding. Zero extension code is executed — all analysis is static regex/text-pattern matching. No Bun installation required for Bun pattern detection.
|
|
305
|
+
> **CVE-2026-48710 (BadHost)** detection uses three independent layers: Layer 1 parses 6 Python manifest formats (requirements.txt, pyproject.toml, poetry.lock, Pipfile, setup.py, setup.cfg) with PEP 440 semver-aware version comparison. Layer 2 scans for 15 known Starlette-downstream packages with Tier 1 (HIGH confidence) and Tier 2 (MEDIUM confidence) transitive heuristics, suppressed by explicit `starlette >= 1.0.1` pin. Layer 3 performs function-boundary static analysis on `.py` files for `request.url.path` usage, escalating to MEDIUM severity in auth/middleware contexts and suppressing when `request.scope["path"]` is used in the same function.
|
|
306
|
+
> **TRAPDOOR** campaign detection runs 9 sub-detectors across all package files (README.md, package.json, .md, shell scripts, .cursorrules, CLAUDE.md) for the hardcoded marker P-2024-001, scans for trap-core.js by filename or exact 48,485-byte size, unconditionally blocks publisher asdxzxc, detects outbound references to ddjidd564.github.io or gist.github.com combined with credential-path patterns, scans .cursorrules and CLAUDE.md for zero-width Unicode characters (U+200B, U+200C, U+200D, U+FEFF), flags crypto/DeFi-themed packages <30 days old with no prior version history, detects simultaneous Fernet and ECDH/createECDH usage in postinstall JS, and identifies sts.amazonaws.com and api.github.com/user calls in postinstall hooks.
|
|
307
|
+
> **NODE_IPC_COMPROMISE** detection intercepts the expired-domain takeover attack across 11 dimensions: version blocklist with safe-pin recommendations (9.1.5 for 9.x, 12.0.0 for 12.x), tarball SHA-256 hash verification against known malicious hashes, CJS vs ESM size comparison with IIFE suffix pattern detection for injected payload identification, DNS resolver pattern analysis (dns.promises.Resolver + setServers with non-public IP + resolveTxt), bootstrap domain and C2 IP detection, resolveTxt() with bt.node.js zone references, setImmediate() runtime trigger detection, ~/nt-*/ staging artifact path identification, publisher account verification against unauthorized account atiertant, and lockfile scanning for compromised version resolution with safe-pin suggestions.
|
|
290
308
|
> See [`docs/attack-taxonomy.md`](docs/attack-taxonomy.md) for full evasion surface documentation and PoC examples.
|
|
291
309
|
|
|
292
310
|
---
|
|
@@ -371,6 +389,8 @@ Campaign detectors use seed IOC files for known-malicious fingerprints:
|
|
|
371
389
|
| IOC File | Detector | Types |
|
|
372
390
|
|----------|----------|-------|
|
|
373
391
|
| `backend/detectors/mini-shai-hulud/iocs.json` | Mini Shai-Hulud (Waves 1–3) | `packageScope`, `publisherAccount`, `sha512`, `extensionId` |
|
|
392
|
+
| `backend/detectors/trapdoor/iocs.json` | TrapDoor | `publisherAccount`, `campaignMarker`, `payloadFilename`, `payloadSize`, `xorKey`, `c2Domain`, `gistDomain` |
|
|
393
|
+
| `backend/detectors/node-ipc-compromise/iocs.json` | node-ipc compromise | `publisherAccount`, `c2Domain`, `c2IP`, `exfilZone`, `payloadHash` |
|
|
374
394
|
| `backend/vsix-scan/vsix-iocs.json` | VSIX extension scan | `extensionId`, `publisherAccount`, `orphanCommitHash` |
|
|
375
395
|
|
|
376
396
|
IOC files follow a unified schema (`iocs: [{ type, value, ... }]`) and are loaded at module init. Update them from your threat intel feed to extend detection coverage without code changes.
|
|
@@ -645,7 +665,7 @@ See the [Docker quick-start section](#-run-lateosnpm-scan-anywhere-with-docker--
|
|
|
645
665
|
|
|
646
666
|
### Free tier (shipped)
|
|
647
667
|
|
|
648
|
-
- All 11 ATK detectors + **MEGALODON** CI/CD campaign detection (D1–D6) + **HF_IMPERSONATION** detector + **MINI_SHAI_HULUD** worm campaign (D1–D7, 3 waves) + **VSIX_SCAN** extension supply chain scan (6 detectors)
|
|
668
|
+
- All 11 ATK detectors + **MEGALODON** CI/CD campaign detection (D1–D6) + **HF_IMPERSONATION** detector + **MINI_SHAI_HULUD** worm campaign (D1–D7, 3 waves) + **VSIX_SCAN** extension supply chain scan (6 detectors) + **CVE-2026-48710 (BadHost)** Python vulnerability detection (3 layers) + **TRAPDOOR** cross-ecosystem attack detection (9 rules) + **NODE_IPC_COMPROMISE** expired-domain hijack detection (11 rules)
|
|
649
669
|
- SBOM output (CycloneDX + SPDX)
|
|
650
670
|
- HTML, text, and compliance reports (NIST + EU CRA)
|
|
651
671
|
- Policy-as-code engine (YAML)
|
|
@@ -724,6 +744,12 @@ node --test test/detectors-corpus.test.js
|
|
|
724
744
|
- `test/vsix-scan/known-ioc.test.js` — 4 known IOC tests (extensionId, publisher window, outside window)
|
|
725
745
|
- `test/vsix-scan/exfil-pattern.test.js` — 5 exfil pattern tests (creds, DNS tunnel, AES+RSA, anti-analysis, silent)
|
|
726
746
|
- `test/vsix-scan/integration.test.js` — 4 integration tests (Nx Console CRITICAL, safe version clean, orphan commit, skipNetwork)
|
|
747
|
+
- `test/cve-2026-48710-badhost/manifest.test.js` — 13 Python manifest parsing tests (requirements.txt, pyproject.toml, poetry.lock, version edge cases)
|
|
748
|
+
- `test/cve-2026-48710-badhost/transitive.test.js` — 7 transitive dependency tests (Tier 1/2, fastapi version gating, pin suppression)
|
|
749
|
+
- `test/cve-2026-48710-badhost/codePattern.test.js` — 6 static code pattern tests (auth context, INFO fallthrough, scope suppression)
|
|
750
|
+
- `test/cve-2026-48710-badhost/integration.test.js` — 4 integration tests (end-to-end composite findings, clean project, no Python files)
|
|
751
|
+
- `test/trapdoor.test.js` — 40 TrapDoor campaign detection tests (D1–D9: campaign marker, payload fingerprint, publisher blocklist, Gist exfil, AI poisoning, lure name, crypto primitives, XOR key, credential validation)
|
|
752
|
+
- `test/node-ipc.test.js` — 37 node-ipc compromise detection tests (D1–D11: version blocklist, tarball hash, CJS injection, payload hash, DNS C2 pattern, bootstrap resolver, DNS TXT exfil, runtime trigger, temp artifact, unauthorized publisher, blast radius)
|
|
727
753
|
- `test/cli.test.js` — commander integration tests (help, version, scan, report, error handling)
|
|
728
754
|
- `test/cli-lockfile.test.js` — scan-lockfile CLI options, yarn/pnpm/monorepo/watch tests
|
|
729
755
|
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@lateos/npm-scan)
|
|
10
10
|
[](LICENSING.md)
|
|
11
11
|
[](package.json)
|
|
12
|
-
[](https://github.com/lateos-ai/npm-scan)
|
|
13
13
|
[](https://github.com/lateos-ai/npm-scan)
|
|
14
14
|
[](https://hub.docker.com/r/lateos/npm-scan)
|
|
15
15
|
[](https://github.com/lateos-ai/npm-scan/actions/workflows/publish.yml)
|
|
@@ -227,6 +227,9 @@ npm-scan report --pdf # 所有扫描(高级版)
|
|
|
227
227
|
| **ATK-009** | 条件/潜伏触发器(CI 检测、基于时间) | 行为 | 🔴 高 | SR-9.2 |
|
|
228
228
|
| **ATK-010** | 沙箱逃逸 / 反分析 | 行为 | 🟠 中 | SR-10.3 |
|
|
229
229
|
| **ATK-011** | 传递性传播(蠕虫式横向扩散) | 行为 | 🔴 高 | SR-11.4 |
|
|
230
|
+
| **CVE-2026-48710** | BadHost — Starlette Host 头注入认证绕过 (CVE-2026-48710, CVSS 7.0)。Python 依赖版本检测 (requirements.txt, pyproject.toml, poetry.lock, Pipfile, setup.py/cfg),传递性启发式检测 (15 个已知下游包:fastapi, vllm, litellm, MCP 服务器等),auth/middleware 上下文中危险 `request.url.path` 使用的静态代码模式扫描,支持 `request.scope["path"]` 抑制 | 静态 + 注册表 | 🔴 高 / 🟠 中 / ℹ️ 信息 | SR-3.1, SR-5.3 |
|
|
231
|
+
| **TRAPDOOR** | TrapDoor 跨生态系统攻击活动 — 活动标记 P-2024-001,trap-core.js 载荷指纹,发布者黑名单 asdxzxc,基于 Gist 的凭证窃取,AI 上下文注入(零宽 Unicode),加密/DeFi 诱饵名称,Fernet+ECDH 加密,XOR 密钥 cargo-build-helper-2026,STS/GitHub API 凭证验证 | 静态 + 注册表 | 🟠 中 / 🔴 高 / ⚫ 严重 | SR-3.1, SR-5.3, SR-7.5 |
|
|
232
|
+
| **NODE_IPC_COMPROMISE** | node-ipc 供应链入侵(2026年5月14日)— 版本黑名单 (9.1.6/9.2.3/12.0.1) 及安全锁定,tarball SHA-256 验证,CJS 载荷 IIFE 注入检测,DNS 非标准端口 C2 模式,引导解析器 sh.azurestaticprovider.net,DNS TXT 外泄区域 bt.node.js,setImmediate() 运行时触发,~/nt-*/ 临时制品检测,未授权发布者 atiertant,锁定文件影响范围检测并推荐安全固定版本 | 静态 + 注册表 | ⚫ 严重 | SR-3.1, SR-5.3, SR-7.5 |
|
|
230
233
|
|
|
231
234
|
> **如何捕获逃避式攻击:** ATK-009 检测检查 `process.env.CI`、探测主机名或使用时间激活的包。ATK-010 标记 `debugger` 语句、`os.hostname()` 探测和环境指纹采集。ATK-011 追踪同级依赖图以检测蠕虫式传播模式。
|
|
232
235
|
> 完整逃避面文档和 PoC 示例请参阅 [`docs/attack-taxonomy.md`](docs/attack-taxonomy.md)。
|
|
@@ -548,7 +551,7 @@ npm-scan report --html > report.html
|
|
|
548
551
|
|
|
549
552
|
### 免费版(已发布)
|
|
550
553
|
|
|
551
|
-
- 全部 11 个 ATK 检测器(静态 +
|
|
554
|
+
- 全部 11 个 ATK 检测器(静态 + 行为)+ **MEGALODON** + **HF_IMPERSONATION** + **MINI_SHAI_HULUD** + **VSIX_SCAN** + **CVE-2026-48710 (BadHost)** + **TRAPDOOR**(9 条规则)+ **NODE_IPC_COMPROMISE**(11 条规则)
|
|
552
555
|
- SBOM 输出(CycloneDX + SPDX)
|
|
553
556
|
- HTML、文本和合规报告(NIST + EU CRA)
|
|
554
557
|
- 策略即代码引擎(YAML)
|
|
@@ -611,6 +614,12 @@ node --test test/detectors-corpus.test.js
|
|
|
611
614
|
- `test/fetch.test.js` — tarball 提取、临时目录清理
|
|
612
615
|
- `test/policy-edge-cases.test.js` — 抑制、覆盖、加载验证的边缘情况
|
|
613
616
|
- `test/report-snapshots.test.js` — HTML/文本/CRA/PDF 格式断言
|
|
617
|
+
- `test/cve-2026-48710-badhost/manifest.test.js` — 13 个 Python 清单解析测试(requirements.txt, pyproject.toml, poetry.lock, 版本边界情况)
|
|
618
|
+
- `test/cve-2026-48710-badhost/transitive.test.js` — 7 个传递性依赖测试(Tier 1/2, fastapi 版本门控, 固定版本抑制)
|
|
619
|
+
- `test/cve-2026-48710-badhost/codePattern.test.js` — 6 个静态代码模式测试(auth 上下文, INFO 穿透, scope 抑制)
|
|
620
|
+
- `test/cve-2026-48710-badhost/integration.test.js` — 4 个集成测试(端到端复合发现项, 清洁项目, 无 Python 文件)
|
|
621
|
+
- `test/trapdoor.test.js` — 40 个 TrapDoor 活动检测测试(D1–D9:活动标记、载荷指纹、发布者黑名单、Gist 外泄、AI 注入、诱饵名称、加密原语、XOR 密钥、凭证验证)
|
|
622
|
+
- `test/node-ipc.test.js` — 37 个 node-ipc 入侵检测测试(D1–D11:版本黑名单、tarball 哈希、CJS 注入、载荷哈希、DNS C2 模式、引导解析器、DNS TXT 外泄、运行时触发、临时制品、未授权发布者、影响范围)
|
|
614
623
|
- `test/cli.test.js` — commander 集成测试(帮助、版本、扫描、报告、错误处理)
|
|
615
624
|
|
|
616
625
|
### 需要帮助?
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { codePatternAuthFinding, codePatternInfoFinding } from './findings.js';
|
|
2
|
+
|
|
3
|
+
const AUTH_CONTEXT_PATHS = [
|
|
4
|
+
'middleware',
|
|
5
|
+
'auth',
|
|
6
|
+
'security',
|
|
7
|
+
'router',
|
|
8
|
+
'depends',
|
|
9
|
+
'guard',
|
|
10
|
+
'permission',
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const URL_PATH_PATTERN = /request\.url\.path|req\.url\.path|self\.request\.url\.path/g;
|
|
14
|
+
const SCOPE_PATH_PATTERN = /request\.scope\s*\[\s*["']path["']\s*\]|request\.scope\.get\s*\(\s*["']path["']\s*\)/g;
|
|
15
|
+
|
|
16
|
+
function hasAuthContext(filePath) {
|
|
17
|
+
const lower = filePath.toLowerCase();
|
|
18
|
+
return AUTH_CONTEXT_PATHS.some(ctx => lower.includes(ctx));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function findFunctionBoundaries(lines) {
|
|
22
|
+
const functions = [];
|
|
23
|
+
let currentFn = null;
|
|
24
|
+
let fnBodyStart = -1;
|
|
25
|
+
let indent = 0;
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < lines.length; i++) {
|
|
28
|
+
const line = lines[i];
|
|
29
|
+
const defMatch = line.match(/^(def\s+\w+|async\s+def\s+\w+)/);
|
|
30
|
+
if (defMatch) {
|
|
31
|
+
if (currentFn) {
|
|
32
|
+
functions.push({ name: currentFn, startLine: fnBodyStart, endLine: i - 1 });
|
|
33
|
+
}
|
|
34
|
+
currentFn = defMatch[1];
|
|
35
|
+
fnBodyStart = i;
|
|
36
|
+
indent = line.length - line.trimStart().length;
|
|
37
|
+
} else if (currentFn && line.trim() && line.length - line.trimStart().length <= indent && !line.trim().startsWith('#') && !line.trim().startsWith('@')) {
|
|
38
|
+
functions.push({ name: currentFn, startLine: fnBodyStart, endLine: i - 1 });
|
|
39
|
+
currentFn = null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (currentFn) {
|
|
43
|
+
functions.push({ name: currentFn, startLine: fnBodyStart, endLine: lines.length - 1 });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return functions;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function hasScopePathInFunction(lines, fnStart, fnEnd) {
|
|
50
|
+
for (let i = fnStart; i <= fnEnd && i < lines.length; i++) {
|
|
51
|
+
if (SCOPE_PATH_PATTERN.test(lines[i])) return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function scanCodePatterns(allFiles) {
|
|
57
|
+
const findings = [];
|
|
58
|
+
|
|
59
|
+
for (const file of (allFiles || [])) {
|
|
60
|
+
const content = typeof file.content === 'string' ? file.content : '';
|
|
61
|
+
if (!content) continue;
|
|
62
|
+
const path = file.path || '';
|
|
63
|
+
if (!path.endsWith('.py')) continue;
|
|
64
|
+
|
|
65
|
+
const lines = content.split('\n');
|
|
66
|
+
const isAuthContext = hasAuthContext(path);
|
|
67
|
+
const functions = findFunctionBoundaries(lines);
|
|
68
|
+
const suppressedLines = new Set();
|
|
69
|
+
|
|
70
|
+
for (const fn of functions) {
|
|
71
|
+
if (hasScopePathInFunction(lines, fn.startLine, fn.endLine)) {
|
|
72
|
+
for (let i = fn.startLine; i <= fn.endLine && i < lines.length; i++) {
|
|
73
|
+
if (URL_PATH_PATTERN.test(lines[i])) {
|
|
74
|
+
suppressedLines.add(i + 1);
|
|
75
|
+
}
|
|
76
|
+
URL_PATH_PATTERN.lastIndex = 0;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (isAuthContext) {
|
|
82
|
+
let m;
|
|
83
|
+
while ((m = URL_PATH_PATTERN.exec(content)) !== null) {
|
|
84
|
+
const lineNumber = content.slice(0, m.index).split('\n').length;
|
|
85
|
+
if (suppressedLines.has(lineNumber)) continue;
|
|
86
|
+
findings.push(codePatternAuthFinding(path, lineNumber));
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
let m;
|
|
90
|
+
while ((m = URL_PATH_PATTERN.exec(content)) !== null) {
|
|
91
|
+
const lineNumber = content.slice(0, m.index).split('\n').length;
|
|
92
|
+
if (suppressedLines.has(lineNumber)) continue;
|
|
93
|
+
findings.push(codePatternInfoFinding(path, lineNumber));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return findings;
|
|
99
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const CVE = 'CVE-2026-48710';
|
|
2
|
+
const NICKNAME = 'BadHost';
|
|
3
|
+
const CVSS = 7.0;
|
|
4
|
+
const REFERENCES = [
|
|
5
|
+
'https://ostif.org/disclosing-the-badhost-vulnerability-in-starlette/',
|
|
6
|
+
'https://github.com/Kludex/starlette/security/advisories/GHSA-86qp-5c8j-p5mr',
|
|
7
|
+
'https://badhost.org/',
|
|
8
|
+
'https://osv.dev/vulnerability/PYSEC-2026-161',
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
const MITIGATION_NOTE = 'Partial mitigation: Cloudflare and AWS ALB reject malformed Host headers for properly proxied deployments. Direct uvicorn/hypercorn/daphne/granian exposure with no reverse proxy in front is highest risk.';
|
|
12
|
+
|
|
13
|
+
const DEPENDENCY_REMEDIATION = 'Upgrade starlette to >= 1.0.1. If starlette is inherited transitively through fastapi, vllm, litellm, or an MCP server package, upgrade the top-level package to a version that pins starlette >= 1.0.1. Verify with: pip show starlette.';
|
|
14
|
+
|
|
15
|
+
const CODE_REMEDIATION = 'Replace request.url.path with request.scope["path"] for all security-sensitive decisions (auth checks, path allowlists, rate limiting gates). The reconstructed request.url is influenced by the unvalidated Host header in Starlette < 1.0.1.';
|
|
16
|
+
|
|
17
|
+
function makeFinding(overrides = {}) {
|
|
18
|
+
return {
|
|
19
|
+
id: CVE,
|
|
20
|
+
severity: 'high',
|
|
21
|
+
title: `${NICKNAME} — ${overrides.source || 'unknown'}`,
|
|
22
|
+
description: '',
|
|
23
|
+
remediation: '',
|
|
24
|
+
evidence: JSON.stringify({
|
|
25
|
+
cve: CVE,
|
|
26
|
+
nickname: NICKNAME,
|
|
27
|
+
cvss: CVSS,
|
|
28
|
+
references: REFERENCES,
|
|
29
|
+
...overrides,
|
|
30
|
+
}),
|
|
31
|
+
...overrides,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function directDependencyFinding(version, specifier) {
|
|
36
|
+
return makeFinding({
|
|
37
|
+
severity: 'high',
|
|
38
|
+
confidence: 'HIGH',
|
|
39
|
+
source: 'direct-dependency',
|
|
40
|
+
title: `${NICKNAME}: Starlette ${version} vulnerable`,
|
|
41
|
+
description: `Starlette ${version} (${specifier}) is vulnerable to CVE-2026-48710 (BadHost) — authentication bypass via Host header injection. Upgrade to starlette >= 1.0.1.`,
|
|
42
|
+
remediation: `${DEPENDENCY_REMEDIATION} ${MITIGATION_NOTE}`,
|
|
43
|
+
file: null,
|
|
44
|
+
line: null,
|
|
45
|
+
via: null,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function directDependencyUnpinnedFinding() {
|
|
50
|
+
return makeFinding({
|
|
51
|
+
severity: 'high',
|
|
52
|
+
confidence: 'HIGH',
|
|
53
|
+
source: 'direct-dependency-unpinned',
|
|
54
|
+
title: `${NICKNAME}: Starlette unpinned`,
|
|
55
|
+
description: 'Starlette is declared with no version constraint — assume vulnerable to CVE-2026-48710 (BadHost) until pinned to >= 1.0.1.',
|
|
56
|
+
remediation: `${DEPENDENCY_REMEDIATION} ${MITIGATION_NOTE}`,
|
|
57
|
+
file: null,
|
|
58
|
+
line: null,
|
|
59
|
+
via: null,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function transitiveDependencyFinding(packageName, tier) {
|
|
64
|
+
const confidence = tier === 1 ? 'HIGH' : 'MEDIUM';
|
|
65
|
+
const tierLabel = tier === 1 ? 'Tier 1' : 'Tier 2';
|
|
66
|
+
return makeFinding({
|
|
67
|
+
severity: 'high',
|
|
68
|
+
confidence,
|
|
69
|
+
source: 'transitive-dependency',
|
|
70
|
+
title: `${NICKNAME}: Transitive via ${packageName}`,
|
|
71
|
+
description: `Starlette not directly pinned; inherited through ${packageName} (${tierLabel}). ${packageName} depends on Starlette — if its version constraint allows Starlette < 1.0.1, your deployment is vulnerable.`,
|
|
72
|
+
remediation: `${DEPENDENCY_REMEDIATION} ${MITIGATION_NOTE}`,
|
|
73
|
+
file: null,
|
|
74
|
+
line: null,
|
|
75
|
+
via: packageName,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function codePatternAuthFinding(filePath, lineNumber) {
|
|
80
|
+
return makeFinding({
|
|
81
|
+
severity: 'medium',
|
|
82
|
+
confidence: 'MEDIUM',
|
|
83
|
+
source: 'code-pattern',
|
|
84
|
+
title: `${NICKNAME}: Dangerous path extraction in auth/middleware`,
|
|
85
|
+
description: `request.url.path used in auth/middleware context at ${filePath}:${lineNumber} — use request.scope['path'] instead. The reconstructed request.url is influenced by the unvalidated Host header in Starlette < 1.0.1.`,
|
|
86
|
+
remediation: `${CODE_REMEDIATION} ${MITIGATION_NOTE}`,
|
|
87
|
+
file: filePath,
|
|
88
|
+
line: lineNumber,
|
|
89
|
+
via: null,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function codePatternInfoFinding(filePath, lineNumber) {
|
|
94
|
+
return makeFinding({
|
|
95
|
+
severity: 'info',
|
|
96
|
+
confidence: 'LOW',
|
|
97
|
+
source: 'code-pattern',
|
|
98
|
+
title: `${NICKNAME}: request.url.path usage detected`,
|
|
99
|
+
description: `request.url.path used at ${filePath}:${lineNumber} — may be influenced by unvalidated Host header in Starlette < 1.0.1. Verify request.scope['path'] is used for security decisions.`,
|
|
100
|
+
remediation: `${CODE_REMEDIATION} ${MITIGATION_NOTE}`,
|
|
101
|
+
file: filePath,
|
|
102
|
+
line: lineNumber,
|
|
103
|
+
via: null,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { scanFiles } from './manifest.js';
|
|
2
|
+
import { scanTransitive } from './transitive.js';
|
|
3
|
+
import { scanCodePatterns } from './codePattern.js';
|
|
4
|
+
|
|
5
|
+
export async function scan(pkgJson, files = [], registryMeta = null, allFiles = null) {
|
|
6
|
+
const targetFiles = allFiles || files;
|
|
7
|
+
|
|
8
|
+
const manifestFindings = scanFiles(targetFiles);
|
|
9
|
+
const transitiveFindings = scanTransitive(targetFiles);
|
|
10
|
+
const codeFindings = scanCodePatterns(targetFiles);
|
|
11
|
+
|
|
12
|
+
const allFindings = [...manifestFindings, ...transitiveFindings, ...codeFindings];
|
|
13
|
+
|
|
14
|
+
return allFindings;
|
|
15
|
+
}
|