projscan 2.1.0 → 2.2.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.md +26 -25
- package/dist/analyzers/supplyChainCheck.d.ts +2 -0
- package/dist/analyzers/supplyChainCheck.js +400 -0
- package/dist/analyzers/supplyChainCheck.js.map +1 -0
- package/dist/core/issueEngine.js +2 -0
- package/dist/core/issueEngine.js.map +1 -1
- package/dist/core/preflight.js +38 -4
- package/dist/core/preflight.js.map +1 -1
- package/dist/core/review.js +31 -2
- package/dist/core/review.js.map +1 -1
- package/dist/projscan-sbom.cdx.json +4589 -0
- package/dist/tool-manifest.json +2 -2
- package/dist/types.d.ts +5 -1
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
**Agent-first code intelligence.** An MCP server that lets AI coding agents (Claude Code, Codex, Cursor, Gemini, Windsurf, Cline, Continue, Zed — any MCP-aware client) query your codebase — with a CLI for humans and a local plugin layer for team-specific policy and reporting.
|
|
11
11
|
|
|
12
|
-
[AI Agent Quick Start](#ai-agent-integration-mcp) · [CLI Quick Start](#quick-start) · [Commands](#commands) · [Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v2.
|
|
12
|
+
[AI Agent Quick Start](#ai-agent-integration-mcp) · [CLI Quick Start](#quick-start) · [Commands](#commands) · [Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/GUIDE.md) · [Roadmap](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/ROADMAP.md)
|
|
13
13
|
|
|
14
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
14
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/projscan-reporter-plugin.png" alt="projscan reporter plugin running in a macOS-style terminal window with a team health summary" width="700">
|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
AI coding agents are becoming the primary interface to code. Today, when you ask your agent *"which files implement auth?"* or *"what breaks if I bump React from 18 to 19?"* - it either guesses from names, or it shells out to grep and reads raw output not built for it.
|
|
23
23
|
|
|
24
|
-
**projscan is the first code-intelligence tool built for agents, not for humans.** Your agent gets a fast, AST-accurate, context-budget-aware view of your codebase through structured MCP tools. It can run a preflight safety gate before edits or merge, query the import graph, find symbol definitions, preview upgrades, rank hotspots, diff structural changes between refs, surface coupling/cycle hotspots, get an **intent-grounded** one-call PR review (now with new-taint-flow detection that *blocks* unsafe merges, plus an optional natural-language intent arg that labels each finding expected / unexpected / out-of-scope), request structured fix-action prompts for any open issue and **mechanically apply** the safe ones with rollback, ask "what breaks if I change this?" via transitive blast-radius analysis (across registered sibling repos too), surface source-to-sink taint flows, share a durable session across multiple agent invocations, and learn from how you use it — quieting accumulated noise on this specific repo over time without ever phoning home.
|
|
24
|
+
**projscan is the first code-intelligence tool built for agents, not for humans.** Your agent gets a fast, AST-accurate, context-budget-aware view of your codebase through structured MCP tools. It can run a preflight safety gate before edits or merge, including supply-chain IOC evidence, query the import graph, find symbol definitions, preview upgrades, rank hotspots, diff structural changes between refs, surface coupling/cycle hotspots, get an **intent-grounded** one-call PR review (now with new-taint-flow detection that *blocks* unsafe merges, plus an optional natural-language intent arg that labels each finding expected / unexpected / out-of-scope), request structured fix-action prompts for any open issue and **mechanically apply** the safe ones with rollback, ask "what breaks if I change this?" via transitive blast-radius analysis (across registered sibling repos too), surface source-to-sink taint flows, share a durable session across multiple agent invocations, and learn from how you use it — quieting accumulated noise on this specific repo over time without ever phoning home.
|
|
25
25
|
|
|
26
26
|
The stable local plugin platform turns that same pipeline into a team substrate: analyzer plugins add project-specific findings, and reporter plugins render `doctor`, `analyze`, and `ci` in your team's own voice without changing the underlying scan.
|
|
27
27
|
|
|
@@ -33,7 +33,7 @@ Humans get the same thing through the CLI.
|
|
|
33
33
|
npx projscan
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
36
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/projscan-reporter-plugin.gif" alt="projscan doctor rendered through a local reporter plugin in a macOS-style terminal window" width="700">
|
|
37
37
|
|
|
38
38
|
Run `projscan doctor` for a focused health check:
|
|
39
39
|
|
|
@@ -41,7 +41,7 @@ Run `projscan doctor` for a focused health check:
|
|
|
41
41
|
npx projscan doctor
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
44
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20doctor.gif" alt="npx projscan doctor" width="700">
|
|
45
45
|
|
|
46
46
|
## Install
|
|
47
47
|
|
|
@@ -61,8 +61,8 @@ Run inside any repository:
|
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
63
|
projscan # Full project analysis
|
|
64
|
-
projscan preflight --format json # Agent safety gate
|
|
65
|
-
projscan doctor # Health check
|
|
64
|
+
projscan preflight --format json # Agent safety gate with supply-chain evidence
|
|
65
|
+
projscan doctor # Health check, including security and supply-chain risks
|
|
66
66
|
projscan hotspots # Rank files by risk (churn × complexity × issues × ownership)
|
|
67
67
|
projscan search <query> # BM25-ranked search (content + symbols + path)
|
|
68
68
|
projscan file <path> # Drill into a file - purpose, risk, ownership, issues
|
|
@@ -84,17 +84,17 @@ projscan plugin test .projscan-plugins/policy.projscan-plugin.json
|
|
|
84
84
|
PROJSCAN_PLUGINS_PREVIEW=1 projscan doctor --reporter team-radar
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
87
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20--help.gif" alt="npx projscan --help" width="700">
|
|
88
88
|
|
|
89
|
-
For a comprehensive walkthrough, see the **[Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v2.
|
|
89
|
+
For a comprehensive walkthrough, see the **[Full Guide](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/GUIDE.md)**.
|
|
90
90
|
|
|
91
91
|
## Commands
|
|
92
92
|
|
|
93
93
|
| Command | Description |
|
|
94
94
|
|---------|-------------|
|
|
95
95
|
| `projscan analyze` | Full analysis - languages, frameworks, dependencies, issues |
|
|
96
|
-
| `projscan doctor` | Health check - missing tooling, architecture smells, security risks |
|
|
97
|
-
| `projscan preflight` | Agent safety gate - `proceed`, `caution`, or `block` with evidence |
|
|
96
|
+
| `projscan doctor` | Health check - missing tooling, architecture smells, security and supply-chain risks |
|
|
97
|
+
| `projscan preflight` | Agent safety gate - `proceed`, `caution`, or `block` with health, change, plugin, and supply-chain evidence |
|
|
98
98
|
| `projscan hotspots` | Rank files by risk - churn × complexity × issues × ownership |
|
|
99
99
|
| `projscan search <query>` | **BM25-ranked search** - content + symbols + path, with excerpts |
|
|
100
100
|
| `projscan file <path>` | Drill into a file - purpose, risk, ownership, related issues |
|
|
@@ -129,31 +129,31 @@ projscan --help
|
|
|
129
129
|
<details>
|
|
130
130
|
<summary><strong>projscan structure</strong> - Directory tree with file counts</summary>
|
|
131
131
|
|
|
132
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
132
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20structure.gif" alt="npx projscan structure" width="700">
|
|
133
133
|
</details>
|
|
134
134
|
|
|
135
135
|
<details>
|
|
136
136
|
<summary><strong>projscan diagram</strong> - Architecture visualization</summary>
|
|
137
137
|
|
|
138
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
138
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20diagram.gif" alt="npx projscan diagram" width="700">
|
|
139
139
|
</details>
|
|
140
140
|
|
|
141
141
|
<details>
|
|
142
142
|
<summary><strong>projscan dependencies</strong> - Dependency analysis</summary>
|
|
143
143
|
|
|
144
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
144
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20dependencies.gif" alt="npx projscan dependencies" width="700">
|
|
145
145
|
</details>
|
|
146
146
|
|
|
147
147
|
<details>
|
|
148
148
|
<summary><strong>projscan explain</strong> - File explanation</summary>
|
|
149
149
|
|
|
150
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
150
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20explain.gif" alt="npx projscan explain" width="700">
|
|
151
151
|
</details>
|
|
152
152
|
|
|
153
153
|
<details>
|
|
154
154
|
<summary><strong>projscan badge</strong> - Health badge generation</summary>
|
|
155
155
|
|
|
156
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
156
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20badge.gif" alt="npx projscan badge" width="700">
|
|
157
157
|
</details>
|
|
158
158
|
|
|
159
159
|
### Output Formats
|
|
@@ -175,7 +175,7 @@ Run `projscan help` for the generated command-by-command support matrix.
|
|
|
175
175
|
|
|
176
176
|
projscan can load local plugins from `.projscan-plugins/` when `PROJSCAN_PLUGINS_PREVIEW=1` is set. The environment flag is kept for explicit local-code opt-in. Analyzer plugins emit normal projscan issues; reporter plugins render supported CLI commands with team-specific output.
|
|
177
177
|
|
|
178
|
-
**2.0 upgrade notes:** migrating from 1.x or authoring plugins? Start with the [2.0 Migration Guide](https://github.com/abhiyoheswaran1/projscan/blob/v2.
|
|
178
|
+
**2.0 upgrade notes:** migrating from 1.x or authoring plugins? Start with the [2.0 Migration Guide](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/2.0-MIGRATION.md), then use [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/PLUGIN-AUTHORING.md) and the [manifest schema](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/plugin.schema.json) as the stable contract.
|
|
179
179
|
|
|
180
180
|
```bash
|
|
181
181
|
projscan plugin list
|
|
@@ -184,9 +184,9 @@ PROJSCAN_PLUGINS_PREVIEW=1 projscan doctor --reporter team-radar
|
|
|
184
184
|
PROJSCAN_PLUGINS_PREVIEW=1 projscan ci --reporter team-radar --min-score 80
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
187
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/projscan-reporter-plugin.gif" alt="projscan local reporter plugin rendering a team health report" width="700">
|
|
188
188
|
|
|
189
|
-
Reporter plugins are intentionally CLI-only. MCP tools keep returning structured JSON-compatible payloads so agents can reason over stable data, while humans can get a polished local report for their team. Custom presentation, team-branded summaries, and white-label reports belong in reporter plugins rather than new core HTML theming flags. See [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v2.
|
|
189
|
+
Reporter plugins are intentionally CLI-only. MCP tools keep returning structured JSON-compatible payloads so agents can reason over stable data, while humans can get a polished local report for their team. Custom presentation, team-branded summaries, and white-label reports belong in reporter plugins rather than new core HTML theming flags. See [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/PLUGIN-AUTHORING.md) for manifest shape, `render(context)`, validation, and the trust model.
|
|
190
190
|
|
|
191
191
|
### Options
|
|
192
192
|
|
|
@@ -330,6 +330,7 @@ projscan reads your source code so it can be useful; it does not send your sourc
|
|
|
330
330
|
| Read source files | every command | no | parses with tree-sitter / Babel; results cached at `.projscan-cache/` |
|
|
331
331
|
| Spawn `git` | `hotspots`, `pr-diff`, `review`, `diff` | git itself may fetch if you run `git fetch` separately; **projscan never invokes `git fetch`** | `env: process.env` is passed so `git` can find its config |
|
|
332
332
|
| Spawn `npm audit` | `audit` only | yes — by `npm`, not by projscan | runs against your local lockfile |
|
|
333
|
+
| Scan supply-chain IOCs | `doctor`, `preflight`, release validation | no | checks manifests, lockfiles, hidden editor hooks, and suspicious install-time payloads against bundled indicators |
|
|
333
334
|
| Load local plugins | only with `PROJSCAN_PLUGINS_PREVIEW=1` | no | imports local JS modules declared in `.projscan-plugins/`; only enable plugins you trust |
|
|
334
335
|
| Load wasm grammars | first parse of a non-JS file | no | served from `dist/grammars/` inside the package; no fetch |
|
|
335
336
|
| Build embeddings | semantic search opt-in only | yes — by `@xenova/transformers`, on first use | model cached locally after first download; remove the peer dep to remove this code path entirely |
|
|
@@ -346,7 +347,7 @@ If you read projscan's [Socket report](https://socket.dev/npm/package/projscan),
|
|
|
346
347
|
### Audit it yourself
|
|
347
348
|
|
|
348
349
|
- **Source is open** at [github.com/abhiyoheswaran1/projscan](https://github.com/abhiyoheswaran1/projscan). The npm tarball matches the `dist/` produced by `npm run build` at the matching tag.
|
|
349
|
-
- **Public API surface is locked** by `scripts/check-stability.mjs`, which runs in CI on every PR and fails on any rename or removal of an MCP tool, CLI command, or exit code. See [`docs/STABILITY.md`](https://github.com/abhiyoheswaran1/projscan/blob/v2.
|
|
350
|
+
- **Public API surface is locked** by `scripts/check-stability.mjs`, which runs in CI on every PR and fails on any rename or removal of an MCP tool, CLI command, or exit code. See [`docs/STABILITY.md`](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/STABILITY.md).
|
|
350
351
|
- **Run it offline:** `npm install -g projscan` followed by anything except `audit` and `--mode semantic` works without network.
|
|
351
352
|
- **Drop privilege further:** in CI, run projscan in a sandbox that disallows network egress; everything except `audit` will pass.
|
|
352
353
|
|
|
@@ -384,7 +385,7 @@ projscan ci --changed-only # Gate only on this PR's diff
|
|
|
384
385
|
projscan ci --format sarif > projscan.sarif # SARIF for Code Scanning
|
|
385
386
|
```
|
|
386
387
|
|
|
387
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
388
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20ci%20--min-score%2070.gif" alt="npx projscan ci --min-score 70" width="700">
|
|
388
389
|
|
|
389
390
|
### GitHub Action (recommended)
|
|
390
391
|
|
|
@@ -453,7 +454,7 @@ Fields:
|
|
|
453
454
|
- `hotspots.limit` / `hotspots.since` - defaults for the `hotspots` command
|
|
454
455
|
- `monorepo.importPolicy` - cross-package import allow/deny rules in monorepos *(0.14+)*
|
|
455
456
|
|
|
456
|
-
See [`docs/GUIDE.md` → Configuration](https://github.com/abhiyoheswaran1/projscan/blob/v2.
|
|
457
|
+
See [`docs/GUIDE.md` → Configuration](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/GUIDE.md#configuration-projscanrc) for the full reference (field types, validation behavior, embedding config in `package.json`, monorepo `importPolicy` semantics).
|
|
457
458
|
|
|
458
459
|
## Tracking Health Over Time
|
|
459
460
|
|
|
@@ -466,7 +467,7 @@ projscan diff # Compare against baseline
|
|
|
466
467
|
projscan diff --format markdown # Markdown diff for PRs
|
|
467
468
|
```
|
|
468
469
|
|
|
469
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
470
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/npx%20projscan%20diff%20--save-baseline.gif" alt="npx projscan diff --save-baseline" width="700">
|
|
470
471
|
|
|
471
472
|
## Hotspots - Where to Fix First
|
|
472
473
|
|
|
@@ -555,7 +556,7 @@ Coverage is also automatically joined into `projscan hotspots` when one of those
|
|
|
555
556
|
|
|
556
557
|
**This is the primary way to use projscan.** `projscan mcp` starts an [MCP](https://modelcontextprotocol.io) server over stdio so AI coding agents can query your codebase with real structural accuracy - not regex, not grep.
|
|
557
558
|
|
|
558
|
-
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.
|
|
559
|
+
<img src="https://raw.githubusercontent.com/abhiyoheswaran1/projscan/v2.2.0/docs/projscan-agent-demo.gif" alt="projscan answering two agent questions: what breaks if I rename buildCodeGraph (impact analysis with definitions, direct callers, transitive reach), and where should I fix first (ranked hotspots with cyclomatic complexity)" width="700">
|
|
559
560
|
|
|
560
561
|
Two questions an agent asks; structural answers in milliseconds. *"What breaks if I rename `buildCodeGraph`?"* → 31 direct callers, 97 files reachable. *"Where should I fix first?"* → ranked hotspots with AST cyclomatic complexity, churn, and ownership signals.
|
|
561
562
|
|
|
@@ -730,7 +731,7 @@ Capability is advertised under `experimental.fileChanged` on `initialize` so cli
|
|
|
730
731
|
- **`projscan_apply_fix`** *(1.6)* - mechanically execute the safe fix templates. Default is dry-run; pass `confirm: true` to write. Atomic writes, per-apply rollback record at `.projscan-cache/rollbacks/<id>.json`. Reverse with `action: "rollback", rollback_id: ...`. Six templates supported at this release: `unused-dependency-*`, `missing-test-framework`, `missing-eslint`, `missing-prettier`, `missing-editorconfig`, `missing-readme`.
|
|
731
732
|
- **`projscan_taint`** *(1.6)* - source-to-sink reachability over the per-function call graph. Built-in defaults cover common JS / Python sources (`process.env`, `req.body`, etc.) and sinks (`exec`, `eval`, `db.query`, etc.). Project-specific names go in `.projscanrc.json` `taint`. `projscan_review` automatically diffs taint flows between base and head and **blocks any PR that introduces a new flow**.
|
|
732
733
|
|
|
733
|
-
For analyzer and reporter plugin authoring, manifest validation, `--reporter <name>`, and the trust model, see [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v2.
|
|
734
|
+
For analyzer and reporter plugin authoring, manifest validation, `--reporter <name>`, and the trust model, see [Plugin Authoring](https://github.com/abhiyoheswaran1/projscan/blob/v2.2.0/docs/PLUGIN-AUTHORING.md).
|
|
734
735
|
|
|
735
736
|
### Context-window budgeting
|
|
736
737
|
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const DEPENDENCY_SCOPES = [
|
|
4
|
+
'dependencies',
|
|
5
|
+
'devDependencies',
|
|
6
|
+
'optionalDependencies',
|
|
7
|
+
'peerDependencies',
|
|
8
|
+
];
|
|
9
|
+
const LIFECYCLE_SCRIPTS = new Set([
|
|
10
|
+
'preinstall',
|
|
11
|
+
'install',
|
|
12
|
+
'postinstall',
|
|
13
|
+
'prepare',
|
|
14
|
+
'prepublish',
|
|
15
|
+
'prepublishOnly',
|
|
16
|
+
]);
|
|
17
|
+
const HIDDEN_HOOK_FILES = new Set([
|
|
18
|
+
'.claude/settings.json',
|
|
19
|
+
'.vscode/settings.json',
|
|
20
|
+
'.vscode/tasks.json',
|
|
21
|
+
]);
|
|
22
|
+
const PAYLOAD_FILENAMES = new Set(['router_init.js', 'tanstack_runner.js']);
|
|
23
|
+
const MAX_JSON_MANIFEST_BYTES = 2 * 1024 * 1024;
|
|
24
|
+
const MAX_LOCKFILE_BYTES = 25 * 1024 * 1024;
|
|
25
|
+
const MAX_JS_PAYLOAD_SCAN_BYTES = 5 * 1024 * 1024;
|
|
26
|
+
const LARGE_JS_PAYLOAD_BYTES = 1024 * 1024;
|
|
27
|
+
const GITHUB_COMMIT_REF = /#[0-9a-f]{7,40}$/i;
|
|
28
|
+
const KNOWN_CONTENT_IOCS = [
|
|
29
|
+
{
|
|
30
|
+
value: 'github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c',
|
|
31
|
+
label: 'Mini Shai-Hulud malicious TanStack git dependency',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: '79ac49eedf774dd4b0cfa308722bc463cfe5885c',
|
|
35
|
+
label: 'Mini Shai-Hulud malicious TanStack git ref',
|
|
36
|
+
},
|
|
37
|
+
{ value: '@tanstack/setup', label: 'Mini Shai-Hulud fictitious package' },
|
|
38
|
+
{ value: 'git-tanstack.com', label: 'Mini Shai-Hulud lookalike domain' },
|
|
39
|
+
{ value: 'gh-token-monitor', label: 'GitHub token monitor persistence marker' },
|
|
40
|
+
{ value: 'filev2.getsession.org', label: 'Mini Shai-Hulud exfiltration network' },
|
|
41
|
+
{ value: 'seed1.getsession.org', label: 'Mini Shai-Hulud exfiltration network' },
|
|
42
|
+
{ value: 'seed2.getsession.org', label: 'Mini Shai-Hulud exfiltration network' },
|
|
43
|
+
{ value: 'seed3.getsession.org', label: 'Mini Shai-Hulud exfiltration network' },
|
|
44
|
+
{ value: 'litter.catbox.moe/h8nc9u.js', label: 'Mini Shai-Hulud second-stage payload URL' },
|
|
45
|
+
{ value: 'litter.catbox.moe/7rrc6l.mjs', label: 'Mini Shai-Hulud second-stage payload URL' },
|
|
46
|
+
];
|
|
47
|
+
const HIDDEN_HOOK_DANGER_PATTERNS = [
|
|
48
|
+
{ pattern: /gh-token-monitor/i, label: 'GitHub token monitor persistence marker' },
|
|
49
|
+
{ pattern: /git-tanstack\.com/i, label: 'Mini Shai-Hulud lookalike domain' },
|
|
50
|
+
{ pattern: /router_init\.js/i, label: 'Mini Shai-Hulud payload filename' },
|
|
51
|
+
{ pattern: /rm\s+-rf\s+(?:~|\$HOME|\/)/i, label: 'destructive home/root delete command' },
|
|
52
|
+
{ pattern: /pkill\s+-f\s+gh-token-monitor/i, label: 'token-monitor process control' },
|
|
53
|
+
{ pattern: /curl\b.+\|\s*(?:sh|bash)/i, label: 'download-and-execute shell pipeline' },
|
|
54
|
+
];
|
|
55
|
+
const OBFUSCATION_MARKERS = [
|
|
56
|
+
/while\s*\(\s*!!\[\]\s*\)/,
|
|
57
|
+
/_0x[a-f0-9]{4,}/i,
|
|
58
|
+
/String\s*\[\s*['"]fromCharCode['"]\s*\]/,
|
|
59
|
+
/\bFunction\s*\(\s*['"]/,
|
|
60
|
+
/\beval\s*\(/,
|
|
61
|
+
];
|
|
62
|
+
const MALICIOUS_PACKAGE_VERSIONS = new Map(Object.entries({
|
|
63
|
+
'@tanstack/arktype-adapter': ['1.166.12', '1.166.15'],
|
|
64
|
+
'@tanstack/eslint-plugin-router': ['1.161.9', '1.161.12'],
|
|
65
|
+
'@tanstack/eslint-plugin-start': ['0.0.4', '0.0.7'],
|
|
66
|
+
'@tanstack/history': ['1.161.9', '1.161.12'],
|
|
67
|
+
'@tanstack/nitro-v2-vite-plugin': ['1.154.12', '1.154.15'],
|
|
68
|
+
'@tanstack/react-router': ['1.169.5', '1.169.8'],
|
|
69
|
+
'@tanstack/react-router-devtools': ['1.166.16', '1.166.19'],
|
|
70
|
+
'@tanstack/react-router-ssr-query': ['1.166.15', '1.166.18'],
|
|
71
|
+
'@tanstack/react-start': ['1.167.68', '1.167.71'],
|
|
72
|
+
'@tanstack/react-start-client': ['1.166.51', '1.166.54'],
|
|
73
|
+
'@tanstack/react-start-rsc': ['0.0.47', '0.0.50'],
|
|
74
|
+
'@tanstack/react-start-server': ['1.166.55', '1.166.58'],
|
|
75
|
+
'@tanstack/router-cli': ['1.166.46', '1.166.49'],
|
|
76
|
+
'@tanstack/router-core': ['1.169.5', '1.169.8'],
|
|
77
|
+
'@tanstack/router-devtools': ['1.166.16', '1.166.19'],
|
|
78
|
+
'@tanstack/router-devtools-core': ['1.167.6', '1.167.9'],
|
|
79
|
+
'@tanstack/router-generator': ['1.166.45', '1.166.48'],
|
|
80
|
+
'@tanstack/router-plugin': ['1.167.38', '1.167.41'],
|
|
81
|
+
'@tanstack/router-ssr-query-core': ['1.168.3', '1.168.6'],
|
|
82
|
+
'@tanstack/router-utils': ['1.161.11', '1.161.14'],
|
|
83
|
+
'@tanstack/router-vite-plugin': ['1.166.53', '1.166.56'],
|
|
84
|
+
'@tanstack/solid-router': ['1.169.5', '1.169.8'],
|
|
85
|
+
'@tanstack/solid-router-devtools': ['1.166.16', '1.166.19'],
|
|
86
|
+
'@tanstack/solid-router-ssr-query': ['1.166.15', '1.166.18'],
|
|
87
|
+
'@tanstack/solid-start': ['1.167.65', '1.167.68'],
|
|
88
|
+
'@tanstack/solid-start-client': ['1.166.50', '1.166.53'],
|
|
89
|
+
'@tanstack/solid-start-server': ['1.166.54', '1.166.57'],
|
|
90
|
+
'@tanstack/start-client-core': ['1.168.5', '1.168.8'],
|
|
91
|
+
'@tanstack/start-fn-stubs': ['1.161.9', '1.161.12'],
|
|
92
|
+
'@tanstack/start-plugin-core': ['1.169.23', '1.169.26'],
|
|
93
|
+
'@tanstack/start-server-core': ['1.167.33', '1.167.36'],
|
|
94
|
+
'@tanstack/start-static-server-functions': ['1.166.44', '1.166.47'],
|
|
95
|
+
'@tanstack/start-storage-context': ['1.166.38', '1.166.41'],
|
|
96
|
+
'@tanstack/valibot-adapter': ['1.166.12', '1.166.15'],
|
|
97
|
+
'@tanstack/virtual-file-routes': ['1.161.10', '1.161.13'],
|
|
98
|
+
'@tanstack/vue-router': ['1.169.5', '1.169.8'],
|
|
99
|
+
'@tanstack/vue-router-devtools': ['1.166.16', '1.166.19'],
|
|
100
|
+
'@tanstack/vue-router-ssr-query': ['1.166.15', '1.166.18'],
|
|
101
|
+
'@tanstack/vue-start': ['1.167.61', '1.167.64'],
|
|
102
|
+
'@tanstack/vue-start-client': ['1.166.46', '1.166.49'],
|
|
103
|
+
'@tanstack/vue-start-server': ['1.166.50', '1.166.53'],
|
|
104
|
+
'@tanstack/zod-adapter': ['1.166.12', '1.166.15'],
|
|
105
|
+
}).map(([name, versions]) => [name, new Set(versions)]));
|
|
106
|
+
export async function check(rootPath, files) {
|
|
107
|
+
const issues = [];
|
|
108
|
+
const seen = new Set();
|
|
109
|
+
for (const file of files) {
|
|
110
|
+
if (isPackageManifest(file)) {
|
|
111
|
+
await scanPackageManifest(file, issues, seen);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (isPackageLock(file)) {
|
|
115
|
+
await scanPackageLock(file, issues, seen);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (HIDDEN_HOOK_FILES.has(normalizePath(file.relativePath))) {
|
|
119
|
+
await scanHiddenHook(file, issues, seen);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (isJavaScriptPayloadCandidate(file)) {
|
|
123
|
+
await scanJavaScriptPayload(file, issues, seen);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return issues;
|
|
127
|
+
}
|
|
128
|
+
async function scanPackageManifest(file, issues, seen) {
|
|
129
|
+
const manifest = await readJson(file.absolutePath, MAX_JSON_MANIFEST_BYTES);
|
|
130
|
+
if (!manifest)
|
|
131
|
+
return;
|
|
132
|
+
for (const scope of DEPENDENCY_SCOPES) {
|
|
133
|
+
const deps = manifest[scope];
|
|
134
|
+
if (!deps || typeof deps !== 'object')
|
|
135
|
+
continue;
|
|
136
|
+
for (const [name, rawSpec] of Object.entries(deps)) {
|
|
137
|
+
const spec = typeof rawSpec === 'string' ? rawSpec.trim() : '';
|
|
138
|
+
if (!spec)
|
|
139
|
+
continue;
|
|
140
|
+
const exactVersion = normalizeExactVersion(spec);
|
|
141
|
+
if (exactVersion && isKnownMaliciousVersion(name, exactVersion)) {
|
|
142
|
+
pushIssue(issues, seen, maliciousPackageIssue(name, exactVersion, file.relativePath));
|
|
143
|
+
}
|
|
144
|
+
const ioc = KNOWN_CONTENT_IOCS.find(({ value }) => spec.includes(value));
|
|
145
|
+
if (ioc) {
|
|
146
|
+
pushIssue(issues, seen, makeIssue({
|
|
147
|
+
id: `supply-chain-known-ioc-${safeId(name)}`,
|
|
148
|
+
title: `Known malicious dependency IOC: ${name}`,
|
|
149
|
+
description: `${name} is declared as "${spec}", which matches ${ioc.label}. Remove the dependency, delete node_modules and lockfiles, reinstall from clean sources, and rotate secrets on any machine that installed it.`,
|
|
150
|
+
severity: 'error',
|
|
151
|
+
file: file.relativePath,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
else if (isGithubCommitDependency(spec)) {
|
|
155
|
+
pushIssue(issues, seen, makeIssue({
|
|
156
|
+
id: `supply-chain-git-dependency-${safeId(name)}`,
|
|
157
|
+
title: `Dependency resolves directly to a GitHub commit: ${name}`,
|
|
158
|
+
description: `The ${scope} entry "${name}" points at "${spec}". GitHub commit dependencies can bypass normal registry review and can run lifecycle scripts during install; pin a vetted registry package or remove the dependency.`,
|
|
159
|
+
severity: 'warning',
|
|
160
|
+
file: file.relativePath,
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (manifest.scripts && typeof manifest.scripts === 'object') {
|
|
166
|
+
for (const [scriptName, rawCommand] of Object.entries(manifest.scripts)) {
|
|
167
|
+
if (!LIFECYCLE_SCRIPTS.has(scriptName))
|
|
168
|
+
continue;
|
|
169
|
+
const command = typeof rawCommand === 'string' ? rawCommand : String(rawCommand);
|
|
170
|
+
if (!shouldFlagLifecycleScript(scriptName, command))
|
|
171
|
+
continue;
|
|
172
|
+
pushIssue(issues, seen, makeIssue({
|
|
173
|
+
id: `supply-chain-lifecycle-${scriptName}`,
|
|
174
|
+
title: `Install lifecycle script present: ${scriptName}`,
|
|
175
|
+
description: `The package manifest defines "${scriptName}": "${command}". Install lifecycle scripts execute during dependency installation and are a common supply-chain execution path; verify this script before release or install.`,
|
|
176
|
+
severity: 'warning',
|
|
177
|
+
file: file.relativePath,
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async function scanPackageLock(file, issues, seen) {
|
|
183
|
+
const lock = await readJson(file.absolutePath, MAX_LOCKFILE_BYTES);
|
|
184
|
+
if (!lock)
|
|
185
|
+
return;
|
|
186
|
+
for (const [entryPath, entry] of Object.entries(lock.packages ?? {})) {
|
|
187
|
+
const name = packageNameFromLockPath(entryPath);
|
|
188
|
+
const version = typeof entry.version === 'string' ? entry.version : null;
|
|
189
|
+
if (name && version && isKnownMaliciousVersion(name, version)) {
|
|
190
|
+
pushIssue(issues, seen, maliciousPackageIssue(name, version, file.relativePath));
|
|
191
|
+
}
|
|
192
|
+
const resolved = typeof entry.resolved === 'string' ? entry.resolved : '';
|
|
193
|
+
const resolvedIoc = KNOWN_CONTENT_IOCS.find(({ value }) => resolved.includes(value));
|
|
194
|
+
if (resolvedIoc) {
|
|
195
|
+
pushIssue(issues, seen, makeIssue({
|
|
196
|
+
id: `supply-chain-known-ioc-${safeId(name ?? entryPath)}`,
|
|
197
|
+
title: `Known malicious lockfile IOC: ${name ?? entryPath}`,
|
|
198
|
+
description: `The lockfile package entry resolves through ${resolvedIoc.label}. Remove the dependency, delete node_modules and lockfiles, reinstall from clean sources, and rotate secrets on any machine that installed it.`,
|
|
199
|
+
severity: 'error',
|
|
200
|
+
file: file.relativePath,
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
const manifestDeps = { ...(entry.dependencies ?? {}), ...(entry.optionalDependencies ?? {}) };
|
|
204
|
+
for (const [depName, rawSpec] of Object.entries(manifestDeps)) {
|
|
205
|
+
const spec = typeof rawSpec === 'string' ? rawSpec : '';
|
|
206
|
+
const ioc = KNOWN_CONTENT_IOCS.find(({ value }) => spec.includes(value) || resolved.includes(value));
|
|
207
|
+
if (!ioc)
|
|
208
|
+
continue;
|
|
209
|
+
pushIssue(issues, seen, makeIssue({
|
|
210
|
+
id: `supply-chain-known-ioc-${safeId(depName)}`,
|
|
211
|
+
title: `Known malicious lockfile IOC: ${depName}`,
|
|
212
|
+
description: `The lockfile contains ${ioc.label}. Remove the dependency, delete node_modules and lockfiles, reinstall from clean sources, and rotate secrets on any machine that installed it.`,
|
|
213
|
+
severity: 'error',
|
|
214
|
+
file: file.relativePath,
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
for (const [name, entry] of Object.entries(lock.dependencies ?? {})) {
|
|
219
|
+
const version = typeof entry.version === 'string' ? entry.version : null;
|
|
220
|
+
if (version && isKnownMaliciousVersion(name, version)) {
|
|
221
|
+
pushIssue(issues, seen, maliciousPackageIssue(name, version, file.relativePath));
|
|
222
|
+
}
|
|
223
|
+
const resolved = typeof entry.resolved === 'string' ? entry.resolved : '';
|
|
224
|
+
const resolvedIoc = KNOWN_CONTENT_IOCS.find(({ value }) => resolved.includes(value));
|
|
225
|
+
if (resolvedIoc) {
|
|
226
|
+
pushIssue(issues, seen, makeIssue({
|
|
227
|
+
id: `supply-chain-known-ioc-${safeId(name)}`,
|
|
228
|
+
title: `Known malicious lockfile IOC: ${name}`,
|
|
229
|
+
description: `The lockfile dependency resolves through ${resolvedIoc.label}. Remove the dependency, delete node_modules and lockfiles, reinstall from clean sources, and rotate secrets on any machine that installed it.`,
|
|
230
|
+
severity: 'error',
|
|
231
|
+
file: file.relativePath,
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function scanHiddenHook(file, issues, seen) {
|
|
237
|
+
const content = await readText(file.absolutePath, 256 * 1024);
|
|
238
|
+
if (!content)
|
|
239
|
+
return;
|
|
240
|
+
const matched = HIDDEN_HOOK_DANGER_PATTERNS.find(({ pattern }) => pattern.test(content));
|
|
241
|
+
if (!matched)
|
|
242
|
+
return;
|
|
243
|
+
pushIssue(issues, seen, makeIssue({
|
|
244
|
+
id: 'supply-chain-hidden-persistence-hook',
|
|
245
|
+
title: `Hidden editor/agent persistence hook in ${file.relativePath}`,
|
|
246
|
+
description: `${file.relativePath} contains ${matched.label}. Treat this as possible supply-chain persistence: remove the hook, inspect running processes, and rotate credentials if it may have executed.`,
|
|
247
|
+
severity: 'error',
|
|
248
|
+
file: file.relativePath,
|
|
249
|
+
}));
|
|
250
|
+
}
|
|
251
|
+
async function scanJavaScriptPayload(file, issues, seen) {
|
|
252
|
+
const basename = path.basename(file.relativePath);
|
|
253
|
+
if (PAYLOAD_FILENAMES.has(basename)) {
|
|
254
|
+
pushIssue(issues, seen, makeIssue({
|
|
255
|
+
id: `supply-chain-payload-file-${safeId(basename)}`,
|
|
256
|
+
title: `Known malicious payload filename: ${basename}`,
|
|
257
|
+
description: `${basename} matches a known Mini Shai-Hulud payload/helper filename. Remove the file, inspect install artifacts, and rotate credentials on any machine where it may have run.`,
|
|
258
|
+
severity: 'error',
|
|
259
|
+
file: file.relativePath,
|
|
260
|
+
}));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (file.sizeBytes < LARGE_JS_PAYLOAD_BYTES || file.sizeBytes > MAX_JS_PAYLOAD_SCAN_BYTES)
|
|
264
|
+
return;
|
|
265
|
+
const content = await readText(file.absolutePath, MAX_JS_PAYLOAD_SCAN_BYTES);
|
|
266
|
+
if (!content)
|
|
267
|
+
return;
|
|
268
|
+
const ioc = KNOWN_CONTENT_IOCS.find(({ value }) => content.includes(value));
|
|
269
|
+
if (ioc) {
|
|
270
|
+
pushIssue(issues, seen, makeIssue({
|
|
271
|
+
id: `supply-chain-known-ioc-${safeId(basename)}`,
|
|
272
|
+
title: `Known malicious JavaScript IOC in ${file.relativePath}`,
|
|
273
|
+
description: `${file.relativePath} contains ${ioc.label}. Remove the artifact and rotate credentials on any machine where it may have run.`,
|
|
274
|
+
severity: 'error',
|
|
275
|
+
file: file.relativePath,
|
|
276
|
+
}));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const markerCount = OBFUSCATION_MARKERS.filter((pattern) => pattern.test(content)).length;
|
|
280
|
+
const hasLongLine = content.split(/\r?\n/, 4).some((line) => line.length > 50_000);
|
|
281
|
+
if (markerCount >= 2 || (markerCount >= 1 && hasLongLine)) {
|
|
282
|
+
pushIssue(issues, seen, makeIssue({
|
|
283
|
+
id: `supply-chain-obfuscated-payload-${safeId(basename)}`,
|
|
284
|
+
title: `Large obfuscated JavaScript payload: ${file.relativePath}`,
|
|
285
|
+
description: `${file.relativePath} is over 1 MB and contains obfuscation markers often seen in install-time malware. Inspect the artifact before installing or publishing.`,
|
|
286
|
+
severity: 'warning',
|
|
287
|
+
file: file.relativePath,
|
|
288
|
+
}));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function maliciousPackageIssue(name, version, file) {
|
|
292
|
+
return makeIssue({
|
|
293
|
+
id: `supply-chain-malicious-package-${name}`,
|
|
294
|
+
title: `Known malicious package version: ${name}@${version}`,
|
|
295
|
+
description: `${name}@${version} is listed in the May 11, 2026 TanStack Mini Shai-Hulud advisory. Remove the version from manifests/lockfiles, reinstall from a clean lockfile, and rotate credentials on any machine or CI runner that installed it.`,
|
|
296
|
+
severity: 'error',
|
|
297
|
+
file,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function makeIssue(input) {
|
|
301
|
+
return {
|
|
302
|
+
id: input.id,
|
|
303
|
+
title: input.title,
|
|
304
|
+
description: input.description,
|
|
305
|
+
severity: input.severity,
|
|
306
|
+
category: 'supply-chain',
|
|
307
|
+
fixAvailable: false,
|
|
308
|
+
locations: [{ file: input.file, line: 1 }],
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function pushIssue(issues, seen, issue) {
|
|
312
|
+
const file = issue.locations?.[0]?.file ?? '';
|
|
313
|
+
const key = `${issue.id}:${file}`;
|
|
314
|
+
if (seen.has(key))
|
|
315
|
+
return;
|
|
316
|
+
seen.add(key);
|
|
317
|
+
issues.push(issue);
|
|
318
|
+
}
|
|
319
|
+
function isKnownMaliciousVersion(name, version) {
|
|
320
|
+
return MALICIOUS_PACKAGE_VERSIONS.get(name)?.has(version) === true;
|
|
321
|
+
}
|
|
322
|
+
function shouldFlagLifecycleScript(scriptName, command) {
|
|
323
|
+
if (scriptName !== 'prepare')
|
|
324
|
+
return true;
|
|
325
|
+
return (/\b(?:bun|node|deno|python|ruby|bash|sh|curl|wget|powershell|pwsh|npx)\b/i.test(command) ||
|
|
326
|
+
/\b(?:npm\s+exec|pnpm\s+dlx|yarn\s+dlx)\b/i.test(command) ||
|
|
327
|
+
/(?:&&|\|\||\|)/.test(command));
|
|
328
|
+
}
|
|
329
|
+
function normalizeExactVersion(spec) {
|
|
330
|
+
const trimmed = spec.trim();
|
|
331
|
+
if (/^\d+\.\d+\.\d+(?:[-+].*)?$/.test(trimmed))
|
|
332
|
+
return trimmed;
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
function isGithubCommitDependency(spec) {
|
|
336
|
+
if (!GITHUB_COMMIT_REF.test(spec))
|
|
337
|
+
return false;
|
|
338
|
+
const withoutRef = spec.slice(0, spec.lastIndexOf('#'));
|
|
339
|
+
return (/^(?:github:)?[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\.git)?$/i.test(withoutRef) ||
|
|
340
|
+
/^(?:git\+https|https|git):\/\/github\.com\/.+/i.test(withoutRef) ||
|
|
341
|
+
/^(?:git\+ssh|ssh):\/\/git@github\.com[:/].+/i.test(withoutRef) ||
|
|
342
|
+
/^git@github\.com:.+/i.test(withoutRef));
|
|
343
|
+
}
|
|
344
|
+
function isPackageManifest(file) {
|
|
345
|
+
return path.basename(file.relativePath) === 'package.json' && !normalizePath(file.relativePath).includes('/node_modules/');
|
|
346
|
+
}
|
|
347
|
+
function isPackageLock(file) {
|
|
348
|
+
return path.basename(file.relativePath) === 'package-lock.json';
|
|
349
|
+
}
|
|
350
|
+
function isJavaScriptPayloadCandidate(file) {
|
|
351
|
+
const basename = path.basename(file.relativePath);
|
|
352
|
+
return PAYLOAD_FILENAMES.has(basename) || ['.js', '.mjs', '.cjs'].includes(file.extension);
|
|
353
|
+
}
|
|
354
|
+
function packageNameFromLockPath(entryPath) {
|
|
355
|
+
const marker = 'node_modules/';
|
|
356
|
+
const markerIndex = entryPath.lastIndexOf(marker);
|
|
357
|
+
if (markerIndex === -1)
|
|
358
|
+
return null;
|
|
359
|
+
const last = entryPath.slice(markerIndex + marker.length);
|
|
360
|
+
if (!last)
|
|
361
|
+
return null;
|
|
362
|
+
const segments = last.split('/');
|
|
363
|
+
if (segments[0]?.startsWith('@') && segments[1])
|
|
364
|
+
return `${segments[0]}/${segments[1]}`;
|
|
365
|
+
return segments[0] || null;
|
|
366
|
+
}
|
|
367
|
+
function safeId(value) {
|
|
368
|
+
return value.replace(/^@/, '').replace(/[^A-Za-z0-9._/-]+/g, '-').replace(/\/+/g, '-');
|
|
369
|
+
}
|
|
370
|
+
function normalizePath(value) {
|
|
371
|
+
return value.split(path.sep).join('/');
|
|
372
|
+
}
|
|
373
|
+
async function readJson(filePath, maxBytes) {
|
|
374
|
+
const content = await readText(filePath, maxBytes);
|
|
375
|
+
if (!content)
|
|
376
|
+
return null;
|
|
377
|
+
try {
|
|
378
|
+
return JSON.parse(content);
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async function readText(filePath, maxBytes) {
|
|
385
|
+
try {
|
|
386
|
+
const handle = await fs.open(filePath, 'r');
|
|
387
|
+
try {
|
|
388
|
+
const buffer = Buffer.alloc(maxBytes);
|
|
389
|
+
const { bytesRead } = await handle.read(buffer, 0, maxBytes, 0);
|
|
390
|
+
return buffer.subarray(0, bytesRead).toString('utf8');
|
|
391
|
+
}
|
|
392
|
+
finally {
|
|
393
|
+
await handle.close();
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
//# sourceMappingURL=supplyChainCheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supplyChainCheck.js","sourceRoot":"","sources":["../../src/analyzers/supplyChainCheck.ts"],"names":[],"mappings":"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"}
|