supply-chain-guard 4.1.0 → 4.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.
Files changed (42) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/correlation-engine.d.ts +21 -0
  3. package/dist/correlation-engine.d.ts.map +1 -0
  4. package/dist/correlation-engine.js +178 -0
  5. package/dist/correlation-engine.js.map +1 -0
  6. package/dist/dependency-risk-analyzer.d.ts +16 -0
  7. package/dist/dependency-risk-analyzer.d.ts.map +1 -0
  8. package/dist/dependency-risk-analyzer.js +130 -0
  9. package/dist/dependency-risk-analyzer.js.map +1 -0
  10. package/dist/index.d.ts +6 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +14 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/install-hook-scanner.d.ts +26 -0
  15. package/dist/install-hook-scanner.d.ts.map +1 -0
  16. package/dist/install-hook-scanner.js +157 -0
  17. package/dist/install-hook-scanner.js.map +1 -0
  18. package/dist/patterns.d.ts +2 -0
  19. package/dist/patterns.d.ts.map +1 -1
  20. package/dist/patterns.js +78 -1
  21. package/dist/patterns.js.map +1 -1
  22. package/dist/publishing-anomaly-detector.d.ts +27 -0
  23. package/dist/publishing-anomaly-detector.d.ts.map +1 -0
  24. package/dist/publishing-anomaly-detector.js +102 -0
  25. package/dist/publishing-anomaly-detector.js.map +1 -0
  26. package/dist/release-scanner.d.ts +33 -0
  27. package/dist/release-scanner.d.ts.map +1 -0
  28. package/dist/release-scanner.js +99 -0
  29. package/dist/release-scanner.js.map +1 -0
  30. package/dist/reporter.js +33 -3
  31. package/dist/reporter.js.map +1 -1
  32. package/dist/scanner.d.ts.map +1 -1
  33. package/dist/scanner.js +36 -3
  34. package/dist/scanner.js.map +1 -1
  35. package/dist/trust-breakdown.d.ts +12 -0
  36. package/dist/trust-breakdown.d.ts.map +1 -0
  37. package/dist/trust-breakdown.js +137 -0
  38. package/dist/trust-breakdown.js.map +1 -0
  39. package/dist/types.d.ts +50 -0
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/types.js.map +1 -1
  42. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ const program = new commander_1.Command();
20
20
  program
21
21
  .name("supply-chain-guard")
22
22
  .description("Open-source supply-chain security scanner. Detects GlassWorm and similar malware campaigns in npm packages, PyPI packages, code repos, VS Code extensions, and project dependencies.")
23
- .version("4.1.0");
23
+ .version("4.2.0");
24
24
  // ── scan command ────────────────────────────────────────────────────
25
25
  program
26
26
  .command("scan")
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Correlation engine (v4.2) — CORE FEATURE.
3
+ *
4
+ * Aggregates individual findings into incident-level clusters.
5
+ * Links related findings, boosts confidence, generates attack narratives,
6
+ * and reduces noise by grouping related indicators.
7
+ */
8
+ import type { Finding, IncidentCluster } from "./types.js";
9
+ export interface CorrelationResult {
10
+ /** Grouped incident clusters */
11
+ incidents: IncidentCluster[];
12
+ /** Risk score boost from correlations (0-30) */
13
+ riskBoost: number;
14
+ /** Human-readable insights */
15
+ insights: string[];
16
+ }
17
+ /**
18
+ * Correlate findings into incident clusters.
19
+ */
20
+ export declare function correlateFindings(findings: Finding[]): CorrelationResult;
21
+ //# sourceMappingURL=correlation-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"correlation-engine.d.ts","sourceRoot":"","sources":["../src/correlation-engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAY,eAAe,EAAE,MAAM,YAAY,CAAC;AA2JrE,MAAM,WAAW,iBAAiB;IAChC,gCAAgC;IAChC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,iBAAiB,CAoDxE"}
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ /**
3
+ * Correlation engine (v4.2) — CORE FEATURE.
4
+ *
5
+ * Aggregates individual findings into incident-level clusters.
6
+ * Links related findings, boosts confidence, generates attack narratives,
7
+ * and reduces noise by grouping related indicators.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.correlateFindings = correlateFindings;
11
+ const CORRELATION_RULES = [
12
+ // --- Known campaigns ---
13
+ {
14
+ rules: ["GLASSWORM_MARKER", "EVAL_ATOB", "ENV_EXFILTRATION", "SOLANA_MAINNET"],
15
+ minMatch: 2,
16
+ incident: "GlassWorm Campaign",
17
+ severity: "critical",
18
+ confidenceBoost: 0.25,
19
+ narrative: "Multiple GlassWorm indicators detected. This matches the GlassWorm supply-chain malware campaign that uses Solana blockchain for C2 communication.",
20
+ },
21
+ {
22
+ rules: ["CAMPAIGN_CLAUDE_LURE", "RELEASE_EXE_ARTIFACT", "DEAD_DROP_STEAM", "VIDAR_BROWSER_THEFT"],
23
+ minMatch: 2,
24
+ incident: "Claude Code Leak Campaign (Vidar/GhostSocks)",
25
+ severity: "critical",
26
+ confidenceBoost: 0.30,
27
+ narrative: "Matches the April 2026 fake Claude Code campaign distributing Vidar stealer and GhostSocks proxy via GitHub releases with star-farmed repos.",
28
+ },
29
+ {
30
+ rules: ["SHAI_HULUD_WORM", "SHAI_HULUD_CRED_STEAL", "INSTALL_HOOK_NPMRC_READ"],
31
+ minMatch: 2,
32
+ incident: "Shai-Hulud npm Worm",
33
+ severity: "critical",
34
+ confidenceBoost: 0.25,
35
+ narrative: "Self-replicating npm worm that steals .npmrc tokens and publishes infected copies of packages.",
36
+ },
37
+ // --- Infostealer chains ---
38
+ {
39
+ rules: ["DEAD_DROP_STEAM", "DEAD_DROP_TELEGRAM", "VIDAR_BROWSER_THEFT", "VIDAR_WALLET_THEFT", "DROPPER_TEMP_EXEC"],
40
+ minMatch: 2,
41
+ incident: "Infostealer Infection (Vidar/Lumma/RedLine)",
42
+ severity: "critical",
43
+ confidenceBoost: 0.25,
44
+ narrative: "Multiple infostealer indicators: dead-drop resolvers for C2, browser credential theft, and crypto wallet targeting. Likely Vidar, Lumma, or RedLine stealer.",
45
+ },
46
+ {
47
+ rules: ["GHOSTSOCKS_SOCKS5", "PROXY_BACKCONNECT", "DROPPER_TEMP_EXEC"],
48
+ minMatch: 2,
49
+ incident: "Proxy Malware (GhostSocks)",
50
+ severity: "critical",
51
+ confidenceBoost: 0.20,
52
+ narrative: "SOCKS5 proxy infrastructure detected. Infected machines are enrolled as residential proxy nodes for criminal traffic routing.",
53
+ },
54
+ // --- Supply-chain attack chains ---
55
+ {
56
+ rules: ["PUBLISH_MAINTAINER_CHANGE", "INSTALL_HOOK_NETWORK", "IOC_KNOWN_C2_DOMAIN"],
57
+ minMatch: 2,
58
+ incident: "npm Account Takeover",
59
+ severity: "critical",
60
+ confidenceBoost: 0.30,
61
+ narrative: "Maintainer change combined with new install hooks contacting known C2 infrastructure. Strong indicator of npm account compromise.",
62
+ },
63
+ {
64
+ rules: ["PUBLISH_MAINTAINER_CHANGE", "PUBLISH_SCRIPT_ADDED", "INSTALL_HOOK_ENV_HARVEST"],
65
+ minMatch: 2,
66
+ incident: "npm Package Hijack (Credential Theft)",
67
+ severity: "critical",
68
+ confidenceBoost: 0.25,
69
+ narrative: "Package maintainer changed and install scripts added that harvest environment variables. Classic account-takeover-to-credential-theft chain.",
70
+ },
71
+ {
72
+ rules: ["TYPOSQUAT_LEVENSHTEIN", "INSTALL_HOOK_NETWORK", "ENV_EXFILTRATION"],
73
+ minMatch: 2,
74
+ incident: "Typosquatting Attack with Data Exfiltration",
75
+ severity: "critical",
76
+ confidenceBoost: 0.25,
77
+ narrative: "Typosquatted package name combined with install-time network access and environment exfiltration. Active data theft via name confusion.",
78
+ },
79
+ // --- Fake repo chains ---
80
+ {
81
+ rules: ["README_LURE_CRACK", "RELEASE_EXE_ARTIFACT", "REPO_RECENT_CREATION", "REPO_SINGLE_COMMIT"],
82
+ minMatch: 2,
83
+ incident: "Fake Repository Malware Distribution",
84
+ severity: "critical",
85
+ confidenceBoost: 0.25,
86
+ narrative: "Recently created repository with piracy/crack lures and executable releases. Classic fake-repo malware distribution pattern.",
87
+ },
88
+ {
89
+ rules: ["CAMPAIGN_AI_TOOL_LURE", "RELEASE_EXE_ARTIFACT", "RELEASE_7Z_ARCHIVE"],
90
+ minMatch: 2,
91
+ incident: "Fake AI Tool Campaign",
92
+ severity: "critical",
93
+ confidenceBoost: 0.25,
94
+ narrative: "Matches the 2026 campaign impersonating 25+ AI tool brands to distribute infostealers via GitHub releases.",
95
+ },
96
+ // --- CI/CD poisoning ---
97
+ {
98
+ rules: ["GHA_CURL_PIPE_EXEC", "GHA_SECRET_CURL", "GHA_UNPINNED_ACTION"],
99
+ minMatch: 2,
100
+ incident: "CI/CD Pipeline Poisoning",
101
+ severity: "critical",
102
+ confidenceBoost: 0.20,
103
+ narrative: "GitHub Actions workflow downloads and executes remote code while accessing secrets. CI/CD pipeline compromise risk.",
104
+ },
105
+ // --- Obfuscation + exfil = malware ---
106
+ {
107
+ rules: ["EVAL_ATOB", "HIGH_ENTROPY_STRING", "ENV_EXFILTRATION", "DEAD_DROP_TELEGRAM"],
108
+ minMatch: 3,
109
+ incident: "Obfuscated Malware with C2",
110
+ severity: "critical",
111
+ confidenceBoost: 0.20,
112
+ narrative: "Heavy code obfuscation combined with data exfiltration and dead-drop C2 resolution. Confirmed malicious payload.",
113
+ },
114
+ // --- Secrets exposure ---
115
+ {
116
+ rules: ["SECRETS_AWS_KEY", "SECRETS_GITHUB_TOKEN", "SECRETS_PRIVATE_KEY", "SECRETS_NPM_TOKEN", "SECRETS_SSH_KEY_READ"],
117
+ minMatch: 2,
118
+ incident: "Multi-Credential Exposure",
119
+ severity: "critical",
120
+ confidenceBoost: 0.15,
121
+ narrative: "Multiple credential types exposed in code. Either a secrets leak or targeted credential harvesting malware.",
122
+ },
123
+ // --- Lockfile + IOC = compromised dependency ---
124
+ {
125
+ rules: ["IOC_KNOWN_BAD_VERSION", "IOC_KNOWN_C2_DOMAIN"],
126
+ minMatch: 2,
127
+ incident: "Known Compromised Dependency",
128
+ severity: "critical",
129
+ confidenceBoost: 0.30,
130
+ narrative: "Known-bad package version detected alongside C2 infrastructure. This dependency has been confirmed compromised.",
131
+ },
132
+ ];
133
+ // ---------------------------------------------------------------------------
134
+ // Main correlation function
135
+ // ---------------------------------------------------------------------------
136
+ /**
137
+ * Correlate findings into incident clusters.
138
+ */
139
+ function correlateFindings(findings) {
140
+ const ruleSet = new Set(findings.map((f) => f.rule));
141
+ const incidents = [];
142
+ let riskBoost = 0;
143
+ const insights = [];
144
+ let clusterId = 0;
145
+ for (const rule of CORRELATION_RULES) {
146
+ const minMatch = rule.minMatch ?? rule.rules.length;
147
+ const matchedRules = rule.rules.filter((r) => ruleSet.has(r));
148
+ if (matchedRules.length >= minMatch) {
149
+ const id = `incident-${++clusterId}`;
150
+ // Collect all findings matching this correlation
151
+ const clusterFindings = findings.filter((f) => matchedRules.includes(f.rule));
152
+ // Boost confidence on matched findings
153
+ for (const f of clusterFindings) {
154
+ f.correlationId = id;
155
+ f.confidence = Math.min(1.0, (f.confidence ?? 0.8) + rule.confidenceBoost);
156
+ }
157
+ // Calculate compound confidence
158
+ const avgConfidence = clusterFindings.reduce((sum, f) => sum + (f.confidence ?? 0.8), 0) / clusterFindings.length;
159
+ incidents.push({
160
+ id,
161
+ name: rule.incident,
162
+ severity: rule.severity,
163
+ confidence: Math.min(1.0, avgConfidence),
164
+ findings: clusterFindings,
165
+ narrative: rule.narrative,
166
+ indicators: matchedRules,
167
+ });
168
+ riskBoost += Math.round(rule.confidenceBoost * 30);
169
+ insights.push(`${rule.incident}: ${matchedRules.length}/${rule.rules.length} indicators matched (confidence ${(avgConfidence * 100).toFixed(0)}%)`);
170
+ }
171
+ }
172
+ // Cap risk boost at 30
173
+ riskBoost = Math.min(30, riskBoost);
174
+ // Sort by confidence descending
175
+ incidents.sort((a, b) => b.confidence - a.confidence);
176
+ return { incidents, riskBoost, insights };
177
+ }
178
+ //# sourceMappingURL=correlation-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"correlation-engine.js","sourceRoot":"","sources":["../src/correlation-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Dependency risk analyzer (v4.2).
3
+ *
4
+ * Levenshtein-based typosquat detection and namespace squatting.
5
+ * Checks package names against popular packages to detect mimicry.
6
+ */
7
+ import type { Finding } from "./types.js";
8
+ /**
9
+ * Calculate Levenshtein distance between two strings.
10
+ */
11
+ export declare function levenshtein(a: string, b: string): number;
12
+ /**
13
+ * Analyze dependencies for typosquatting and confusion risks.
14
+ */
15
+ export declare function analyzeDependencyRisks(dependencies: Record<string, string>, relativePath: string): Finding[];
16
+ //# sourceMappingURL=dependency-risk-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-risk-analyzer.d.ts","sourceRoot":"","sources":["../src/dependency-risk-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAiC1C;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAsBxD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,YAAY,EAAE,MAAM,GACnB,OAAO,EAAE,CAoEX"}
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ /**
3
+ * Dependency risk analyzer (v4.2).
4
+ *
5
+ * Levenshtein-based typosquat detection and namespace squatting.
6
+ * Checks package names against popular packages to detect mimicry.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.levenshtein = levenshtein;
10
+ exports.analyzeDependencyRisks = analyzeDependencyRisks;
11
+ /** Top 80 most popular npm packages (targets for typosquatting) */
12
+ const POPULAR_PACKAGES = [
13
+ "lodash", "chalk", "express", "react", "axios", "commander", "debug",
14
+ "glob", "minimist", "semver", "uuid", "mkdirp", "rimraf", "yargs",
15
+ "moment", "bluebird", "underscore", "async", "request", "inquirer",
16
+ "colors", "path", "dotenv", "body-parser", "webpack", "typescript",
17
+ "eslint", "prettier", "jest", "mocha", "chai", "sinon", "supertest",
18
+ "mongoose", "sequelize", "pg", "mysql2", "redis", "ioredis",
19
+ "socket.io", "cors", "helmet", "morgan", "cookie-parser", "jsonwebtoken",
20
+ "bcrypt", "passport", "nodemailer", "multer", "sharp", "puppeteer",
21
+ "cheerio", "node-fetch", "got", "superagent", "http-proxy-middleware",
22
+ "ws", "next", "gatsby", "vue", "angular", "svelte", "tailwindcss",
23
+ "postcss", "autoprefixer", "sass", "less", "babel", "esbuild",
24
+ "rollup", "vite", "turbo", "nx", "lerna", "husky", "lint-staged",
25
+ "cross-env", "concurrently", "nodemon", "pm2", "fastify", "koa",
26
+ "hapi", "restify",
27
+ ];
28
+ /** Patterns that suggest internal/private package names */
29
+ const INTERNAL_PATTERNS = [
30
+ /^@[^/]+\/internal-/,
31
+ /^@[^/]+\/private-/,
32
+ /^@[^/]+\/.+-service$/,
33
+ /^@[^/]+\/.+-api$/,
34
+ /^@[^/]+\/.+-lib$/,
35
+ /^@[^/]+\/.+-utils$/,
36
+ /^@[^/]+\/.+-common$/,
37
+ /^@[^/]+\/.+-core$/,
38
+ /^@[^/]+\/.+-shared$/,
39
+ ];
40
+ /**
41
+ * Calculate Levenshtein distance between two strings.
42
+ */
43
+ function levenshtein(a, b) {
44
+ const m = a.length;
45
+ const n = b.length;
46
+ const dp = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }, () => 0));
47
+ for (let i = 0; i <= m; i++)
48
+ dp[i][0] = i;
49
+ for (let j = 0; j <= n; j++)
50
+ dp[0][j] = j;
51
+ for (let i = 1; i <= m; i++) {
52
+ for (let j = 1; j <= n; j++) {
53
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
54
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
55
+ }
56
+ }
57
+ return dp[m][n];
58
+ }
59
+ /**
60
+ * Analyze dependencies for typosquatting and confusion risks.
61
+ */
62
+ function analyzeDependencyRisks(dependencies, relativePath) {
63
+ const findings = [];
64
+ const depNames = Object.keys(dependencies);
65
+ for (const name of depNames) {
66
+ // Skip scoped packages for Levenshtein (handled separately)
67
+ if (name.startsWith("@")) {
68
+ // Check internal name patterns on public registry
69
+ for (const pattern of INTERNAL_PATTERNS) {
70
+ if (pattern.test(name)) {
71
+ findings.push({
72
+ rule: "DEP_INTERNAL_NAME_PUBLIC",
73
+ description: `Dependency "${name}" looks like an internal package name. If this is on a public registry, it may be a dependency confusion attack.`,
74
+ severity: "critical",
75
+ file: relativePath,
76
+ confidence: 0.7,
77
+ category: "supply-chain",
78
+ recommendation: `Verify "${name}" is your organization's real package. If not, this is dependency confusion.`,
79
+ });
80
+ break;
81
+ }
82
+ }
83
+ continue;
84
+ }
85
+ // Levenshtein check against popular packages
86
+ for (const popular of POPULAR_PACKAGES) {
87
+ if (name === popular)
88
+ continue; // Exact match = legitimate
89
+ if (Math.abs(name.length - popular.length) > 2)
90
+ continue; // Quick skip
91
+ const dist = levenshtein(name, popular);
92
+ if (dist > 0 && dist <= 2) {
93
+ findings.push({
94
+ rule: "TYPOSQUAT_LEVENSHTEIN",
95
+ description: `Dependency "${name}" is ${dist} edit(s) away from popular package "${popular}". Likely a typosquat.`,
96
+ severity: "high",
97
+ file: relativePath,
98
+ confidence: dist === 1 ? 0.85 : 0.65,
99
+ category: "supply-chain",
100
+ recommendation: `Did you mean "${popular}"? Typosquatting replaces popular packages with malicious copies.`,
101
+ });
102
+ break; // One match per dep is enough
103
+ }
104
+ }
105
+ // Check if name is similar to another direct dependency
106
+ for (const otherName of depNames) {
107
+ if (name === otherName)
108
+ continue;
109
+ if (name.startsWith("@") || otherName.startsWith("@"))
110
+ continue;
111
+ if (Math.abs(name.length - otherName.length) > 2)
112
+ continue;
113
+ const dist = levenshtein(name, otherName);
114
+ if (dist > 0 && dist <= 1) {
115
+ findings.push({
116
+ rule: "TYPOSQUAT_SIMILAR_TO_DEP",
117
+ description: `Dependencies "${name}" and "${otherName}" differ by only ${dist} character(s). One may be a typosquat of the other.`,
118
+ severity: "high",
119
+ file: relativePath,
120
+ confidence: 0.7,
121
+ category: "supply-chain",
122
+ recommendation: `Review both "${name}" and "${otherName}". Only one should be in your dependencies.`,
123
+ });
124
+ break;
125
+ }
126
+ }
127
+ }
128
+ return findings;
129
+ }
130
+ //# sourceMappingURL=dependency-risk-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-risk-analyzer.js","sourceRoot":"","sources":["../src/dependency-risk-analyzer.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -21,5 +21,11 @@ export { scanCargoFiles } from "./cargo-scanner.js";
21
21
  export { scanGoFiles } from "./go-scanner.js";
22
22
  export { checkIOCBlocklist, checkBadVersion } from "./ioc-blocklist.js";
23
23
  export { analyzeGitHubTrust, parseGitHubUrl, scanReadmeLures } from "./github-trust-scanner.js";
24
+ export { analyzeInstallHooks } from "./install-hook-scanner.js";
25
+ export { analyzeDependencyRisks, levenshtein } from "./dependency-risk-analyzer.js";
26
+ export { analyzePublishingAnomalies } from "./publishing-anomaly-detector.js";
27
+ export { scanReleaseArtifacts } from "./release-scanner.js";
28
+ export { correlateFindings } from "./correlation-engine.js";
29
+ export { calculateTrustBreakdown } from "./trust-breakdown.js";
24
30
  export type { Finding, ScanReport, ScanOptions, ScanSummary, Severity, NpmPackageInfo, SolanaMonitorOptions, SolanaTransaction, PatternEntry, WatchlistEntry, WatchlistConfig, WatchlistAlert, } from "./types.js";
25
31
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EACL,aAAa,EACb,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAChG,YAAY,EACV,OAAO,EACP,UAAU,EACV,WAAW,EACX,WAAW,EACX,QAAQ,EACR,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EACL,aAAa,EACb,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,YAAY,EACV,OAAO,EACP,UAAU,EACV,WAAW,EACX,WAAW,EACX,QAAQ,EACR,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * Detects GlassWorm and similar malware campaigns.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.scanReadmeLures = exports.parseGitHubUrl = exports.analyzeGitHubTrust = exports.checkBadVersion = exports.checkIOCBlocklist = exports.scanGoFiles = exports.scanCargoFiles = exports.shannonEntropy = exports.analyzeEntropy = exports.scanGitSecurity = exports.scanConfigFile = exports.scanConfigFiles = exports.scanDockerFile = exports.scanDockerFiles = exports.scanGitHubActionsWorkflows = exports.checkLockfile = exports.formatReport = exports.monitorWatchlist = exports.listWatchlist = exports.removeFromWatchlist = exports.addToWatchlist = exports.saveWatchlist = exports.loadWatchlist = exports.formatAlert = exports.checkWallet = exports.monitorWallet = exports.scanDependencyConfusion = exports.scanVscodeExtension = exports.scanPypiPackage = exports.scanNpmPackage = exports.scan = void 0;
9
+ exports.calculateTrustBreakdown = exports.correlateFindings = exports.scanReleaseArtifacts = exports.analyzePublishingAnomalies = exports.levenshtein = exports.analyzeDependencyRisks = exports.analyzeInstallHooks = exports.scanReadmeLures = exports.parseGitHubUrl = exports.analyzeGitHubTrust = exports.checkBadVersion = exports.checkIOCBlocklist = exports.scanGoFiles = exports.scanCargoFiles = exports.shannonEntropy = exports.analyzeEntropy = exports.scanGitSecurity = exports.scanConfigFile = exports.scanConfigFiles = exports.scanDockerFile = exports.scanDockerFiles = exports.scanGitHubActionsWorkflows = exports.checkLockfile = exports.formatReport = exports.monitorWatchlist = exports.listWatchlist = exports.removeFromWatchlist = exports.addToWatchlist = exports.saveWatchlist = exports.loadWatchlist = exports.formatAlert = exports.checkWallet = exports.monitorWallet = exports.scanDependencyConfusion = exports.scanVscodeExtension = exports.scanPypiPackage = exports.scanNpmPackage = exports.scan = void 0;
10
10
  var scanner_js_1 = require("./scanner.js");
11
11
  Object.defineProperty(exports, "scan", { enumerable: true, get: function () { return scanner_js_1.scan; } });
12
12
  var npm_scanner_js_1 = require("./npm-scanner.js");
@@ -55,4 +55,17 @@ var github_trust_scanner_js_1 = require("./github-trust-scanner.js");
55
55
  Object.defineProperty(exports, "analyzeGitHubTrust", { enumerable: true, get: function () { return github_trust_scanner_js_1.analyzeGitHubTrust; } });
56
56
  Object.defineProperty(exports, "parseGitHubUrl", { enumerable: true, get: function () { return github_trust_scanner_js_1.parseGitHubUrl; } });
57
57
  Object.defineProperty(exports, "scanReadmeLures", { enumerable: true, get: function () { return github_trust_scanner_js_1.scanReadmeLures; } });
58
+ var install_hook_scanner_js_1 = require("./install-hook-scanner.js");
59
+ Object.defineProperty(exports, "analyzeInstallHooks", { enumerable: true, get: function () { return install_hook_scanner_js_1.analyzeInstallHooks; } });
60
+ var dependency_risk_analyzer_js_1 = require("./dependency-risk-analyzer.js");
61
+ Object.defineProperty(exports, "analyzeDependencyRisks", { enumerable: true, get: function () { return dependency_risk_analyzer_js_1.analyzeDependencyRisks; } });
62
+ Object.defineProperty(exports, "levenshtein", { enumerable: true, get: function () { return dependency_risk_analyzer_js_1.levenshtein; } });
63
+ var publishing_anomaly_detector_js_1 = require("./publishing-anomaly-detector.js");
64
+ Object.defineProperty(exports, "analyzePublishingAnomalies", { enumerable: true, get: function () { return publishing_anomaly_detector_js_1.analyzePublishingAnomalies; } });
65
+ var release_scanner_js_1 = require("./release-scanner.js");
66
+ Object.defineProperty(exports, "scanReleaseArtifacts", { enumerable: true, get: function () { return release_scanner_js_1.scanReleaseArtifacts; } });
67
+ var correlation_engine_js_1 = require("./correlation-engine.js");
68
+ Object.defineProperty(exports, "correlateFindings", { enumerable: true, get: function () { return correlation_engine_js_1.correlateFindings; } });
69
+ var trust_breakdown_js_1 = require("./trust-breakdown.js");
70
+ Object.defineProperty(exports, "calculateTrustBreakdown", { enumerable: true, get: function () { return trust_breakdown_js_1.calculateTrustBreakdown; } });
58
71
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,2CAAoC;AAA3B,kGAAA,IAAI,OAAA;AACb,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,qDAAoD;AAA3C,kHAAA,eAAe,OAAA;AACxB,yDAA0D;AAAjD,wHAAA,mBAAmB,OAAA;AAC5B,qEAAoE;AAA3D,kIAAA,uBAAuB,OAAA;AAChC,yDAU6B;AAT3B,kHAAA,aAAa,OAAA;AACb,gHAAA,WAAW,OAAA;AACX,gHAAA,WAAW,OAAA;AACX,kHAAA,aAAa,OAAA;AACb,kHAAA,aAAa,OAAA;AACb,mHAAA,cAAc,OAAA;AACd,wHAAA,mBAAmB,OAAA;AACnB,kHAAA,aAAa,OAAA;AACb,qHAAA,gBAAgB,OAAA;AAElB,6CAA6C;AAApC,2GAAA,YAAY,OAAA;AACrB,6DAAsD;AAA7C,oHAAA,aAAa,OAAA;AACtB,yEAAyE;AAAhE,uIAAA,0BAA0B,OAAA;AACnC,iEAA0E;AAAjE,wHAAA,eAAe,OAAA;AAAE,uHAAA,cAAc,OAAA;AACxC,yDAAsE;AAA7D,oHAAA,eAAe,OAAA;AAAE,mHAAA,cAAc,OAAA;AACxC,mDAAmD;AAA1C,iHAAA,eAAe,OAAA;AACxB,2CAA8D;AAArD,4GAAA,cAAc,OAAA;AAAE,4GAAA,cAAc,OAAA;AACvC,uDAAoD;AAA3C,kHAAA,cAAc,OAAA;AACvB,iDAA8C;AAArC,4GAAA,WAAW,OAAA;AACpB,uDAAwE;AAA/D,qHAAA,iBAAiB,OAAA;AAAE,mHAAA,eAAe,OAAA;AAC3C,qEAAgG;AAAvF,6HAAA,kBAAkB,OAAA;AAAE,yHAAA,cAAc,OAAA;AAAE,0HAAA,eAAe,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,2CAAoC;AAA3B,kGAAA,IAAI,OAAA;AACb,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,qDAAoD;AAA3C,kHAAA,eAAe,OAAA;AACxB,yDAA0D;AAAjD,wHAAA,mBAAmB,OAAA;AAC5B,qEAAoE;AAA3D,kIAAA,uBAAuB,OAAA;AAChC,yDAU6B;AAT3B,kHAAA,aAAa,OAAA;AACb,gHAAA,WAAW,OAAA;AACX,gHAAA,WAAW,OAAA;AACX,kHAAA,aAAa,OAAA;AACb,kHAAA,aAAa,OAAA;AACb,mHAAA,cAAc,OAAA;AACd,wHAAA,mBAAmB,OAAA;AACnB,kHAAA,aAAa,OAAA;AACb,qHAAA,gBAAgB,OAAA;AAElB,6CAA6C;AAApC,2GAAA,YAAY,OAAA;AACrB,6DAAsD;AAA7C,oHAAA,aAAa,OAAA;AACtB,yEAAyE;AAAhE,uIAAA,0BAA0B,OAAA;AACnC,iEAA0E;AAAjE,wHAAA,eAAe,OAAA;AAAE,uHAAA,cAAc,OAAA;AACxC,yDAAsE;AAA7D,oHAAA,eAAe,OAAA;AAAE,mHAAA,cAAc,OAAA;AACxC,mDAAmD;AAA1C,iHAAA,eAAe,OAAA;AACxB,2CAA8D;AAArD,4GAAA,cAAc,OAAA;AAAE,4GAAA,cAAc,OAAA;AACvC,uDAAoD;AAA3C,kHAAA,cAAc,OAAA;AACvB,iDAA8C;AAArC,4GAAA,WAAW,OAAA;AACpB,uDAAwE;AAA/D,qHAAA,iBAAiB,OAAA;AAAE,mHAAA,eAAe,OAAA;AAC3C,qEAAgG;AAAvF,6HAAA,kBAAkB,OAAA;AAAE,yHAAA,cAAc,OAAA;AAAE,0HAAA,eAAe,OAAA;AAC5D,qEAAgE;AAAvD,8HAAA,mBAAmB,OAAA;AAC5B,6EAAoF;AAA3E,qIAAA,sBAAsB,OAAA;AAAE,0HAAA,WAAW,OAAA;AAC5C,mFAA8E;AAArE,4IAAA,0BAA0B,OAAA;AACnC,2DAA4D;AAAnD,0HAAA,oBAAoB,OAAA;AAC7B,iEAA4D;AAAnD,0HAAA,iBAAiB,OAAA;AAC1B,2DAA+D;AAAtD,6HAAA,uBAAuB,OAAA"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Install hook deep analysis scanner (v4.2).
3
+ *
4
+ * Goes beyond basic SUSPICIOUS_SCRIPTS patterns to detect sophisticated
5
+ * install-time attacks: secret harvesting, download-exec chains,
6
+ * obfuscated one-liners, and embedded binary blobs.
7
+ */
8
+ import type { Finding } from "./types.js";
9
+ interface InstallScripts {
10
+ preinstall?: string;
11
+ postinstall?: string;
12
+ install?: string;
13
+ preuninstall?: string;
14
+ postuninstall?: string;
15
+ prepare?: string;
16
+ }
17
+ /**
18
+ * Deep-analyze install hook scripts from package.json.
19
+ */
20
+ export declare function analyzeInstallHooks(scripts: InstallScripts, relativePath: string): Finding[];
21
+ /**
22
+ * Extract install scripts from parsed package.json content.
23
+ */
24
+ export declare function extractInstallScripts(content: string): InstallScripts | null;
25
+ export {};
26
+ //# sourceMappingURL=install-hook-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-hook-scanner.d.ts","sourceRoot":"","sources":["../src/install-hook-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,UAAU,cAAc;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,GACnB,OAAO,EAAE,CA8HX;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GACd,cAAc,GAAG,IAAI,CAevB"}
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /**
3
+ * Install hook deep analysis scanner (v4.2).
4
+ *
5
+ * Goes beyond basic SUSPICIOUS_SCRIPTS patterns to detect sophisticated
6
+ * install-time attacks: secret harvesting, download-exec chains,
7
+ * obfuscated one-liners, and embedded binary blobs.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.analyzeInstallHooks = analyzeInstallHooks;
11
+ exports.extractInstallScripts = extractInstallScripts;
12
+ /**
13
+ * Deep-analyze install hook scripts from package.json.
14
+ */
15
+ function analyzeInstallHooks(scripts, relativePath) {
16
+ const findings = [];
17
+ const hookNames = [
18
+ "preinstall", "postinstall", "install", "preuninstall", "postuninstall", "prepare",
19
+ ];
20
+ for (const hook of hookNames) {
21
+ const script = scripts[hook];
22
+ if (!script)
23
+ continue;
24
+ // Network access in install scripts
25
+ if (/(?:fetch|https?\.(?:get|request|post)|axios|got|node-fetch|urllib|curl|wget)\b/i.test(script)) {
26
+ findings.push({
27
+ rule: "INSTALL_HOOK_NETWORK",
28
+ description: `${hook} script makes network requests. Install scripts should not access the network.`,
29
+ severity: "critical",
30
+ file: relativePath,
31
+ match: truncate(`${hook}: ${script}`),
32
+ confidence: 0.9,
33
+ category: "supply-chain",
34
+ recommendation: "Remove network calls from install scripts. Use explicit build steps instead.",
35
+ });
36
+ }
37
+ // Download + execute chain
38
+ if (/(?:curl|wget|fetch).*(?:chmod\s+\+x|exec|spawn|child_process|\.\/|bash|sh\s|node\s)/i.test(script) ||
39
+ /(?:exec|spawn).*(?:curl|wget|fetch)/i.test(script)) {
40
+ findings.push({
41
+ rule: "INSTALL_HOOK_DOWNLOAD_EXEC",
42
+ description: `${hook} script downloads and executes code. This is the #1 supply-chain attack vector.`,
43
+ severity: "critical",
44
+ file: relativePath,
45
+ match: truncate(`${hook}: ${script}`),
46
+ confidence: 0.95,
47
+ category: "malware",
48
+ recommendation: "Never download and execute code during npm install. This is almost certainly malicious.",
49
+ });
50
+ }
51
+ // Environment variable harvesting (secrets)
52
+ if (/process\.env\.(?:AWS|GITHUB|NPM|GH_|AZURE|GCP|DOCKER|CI|TRAVIS|CIRCLE|JENKINS|SECRET|TOKEN|KEY|PASSWORD|CREDENTIAL)/i.test(script)) {
53
+ findings.push({
54
+ rule: "INSTALL_HOOK_ENV_HARVEST",
55
+ description: `${hook} script accesses sensitive environment variables (secrets, tokens, keys).`,
56
+ severity: "critical",
57
+ file: relativePath,
58
+ match: truncate(`${hook}: ${script}`),
59
+ confidence: 0.85,
60
+ category: "supply-chain",
61
+ recommendation: "Install scripts should never read CI/CD secrets or API tokens.",
62
+ });
63
+ }
64
+ // .npmrc / credential file access
65
+ if (/\.npmrc|npm_config_|_authToken|\.ssh[/\\]|id_rsa|id_ed25519|\.gnupg|\.aws\/credentials/i.test(script)) {
66
+ findings.push({
67
+ rule: "INSTALL_HOOK_NPMRC_READ",
68
+ description: `${hook} script accesses credential files (.npmrc, SSH keys, AWS credentials).`,
69
+ severity: "critical",
70
+ file: relativePath,
71
+ match: truncate(`${hook}: ${script}`),
72
+ confidence: 0.9,
73
+ category: "malware",
74
+ recommendation: "Install scripts must not read credential files. This is credential theft.",
75
+ });
76
+ }
77
+ // .env file access
78
+ if (/\.env\b|dotenv|require\s*\(\s*['"]dotenv/i.test(script)) {
79
+ findings.push({
80
+ rule: "INSTALL_HOOK_DOTENV_READ",
81
+ description: `${hook} script reads .env files. Environment files contain secrets.`,
82
+ severity: "high",
83
+ file: relativePath,
84
+ match: truncate(`${hook}: ${script}`),
85
+ confidence: 0.7,
86
+ category: "supply-chain",
87
+ recommendation: "Install scripts should not load .env files.",
88
+ });
89
+ }
90
+ // Obfuscated script content
91
+ if (/(?:atob|btoa|Buffer\.from|decodeURIComponent|unescape|String\.fromCharCode)\s*\(/i.test(script)) {
92
+ findings.push({
93
+ rule: "INSTALL_HOOK_OBFUSCATED",
94
+ description: `${hook} script contains encoding/decoding operations. Obfuscated install scripts are a strong malware indicator.`,
95
+ severity: "high",
96
+ file: relativePath,
97
+ match: truncate(`${hook}: ${script}`),
98
+ confidence: 0.8,
99
+ category: "malware",
100
+ recommendation: "Decode the obfuscated content and inspect it before running npm install.",
101
+ });
102
+ }
103
+ // Long one-liner (> 500 chars)
104
+ if (script.length > 500 && !script.includes("\n")) {
105
+ findings.push({
106
+ rule: "INSTALL_HOOK_LONG_ONELINER",
107
+ description: `${hook} script is a ${script.length}-character one-liner. Long single-line scripts are often obfuscated malware.`,
108
+ severity: "medium",
109
+ file: relativePath,
110
+ match: truncate(`${hook}: ${script}`),
111
+ confidence: 0.6,
112
+ category: "supply-chain",
113
+ recommendation: "Review this script carefully. Legitimate build scripts are rarely this long on one line.",
114
+ });
115
+ }
116
+ // Embedded binary blob (base64 > 1KB)
117
+ const b64Match = script.match(/[A-Za-z0-9+/=]{1000,}/);
118
+ if (b64Match) {
119
+ findings.push({
120
+ rule: "INSTALL_HOOK_BINARY_BLOB",
121
+ description: `${hook} script contains an embedded binary blob (${b64Match[0].length} chars). Likely an encoded executable payload.`,
122
+ severity: "high",
123
+ file: relativePath,
124
+ match: truncate(`${hook}: ${b64Match[0].substring(0, 60)}...`),
125
+ confidence: 0.85,
126
+ category: "malware",
127
+ recommendation: "Decode this base64 blob and inspect it. Embedded payloads in install scripts are malware.",
128
+ });
129
+ }
130
+ }
131
+ return findings;
132
+ }
133
+ /**
134
+ * Extract install scripts from parsed package.json content.
135
+ */
136
+ function extractInstallScripts(content) {
137
+ try {
138
+ const pkg = JSON.parse(content);
139
+ if (!pkg.scripts)
140
+ return null;
141
+ return {
142
+ preinstall: pkg.scripts.preinstall,
143
+ postinstall: pkg.scripts.postinstall,
144
+ install: pkg.scripts.install,
145
+ preuninstall: pkg.scripts.preuninstall,
146
+ postuninstall: pkg.scripts.postuninstall,
147
+ prepare: pkg.scripts.prepare,
148
+ };
149
+ }
150
+ catch {
151
+ return null;
152
+ }
153
+ }
154
+ function truncate(s, max = 120) {
155
+ return s.length > max ? s.substring(0, max) + "..." : s;
156
+ }
157
+ //# sourceMappingURL=install-hook-scanner.js.map