@nexus_js/audit 0.7.0 → 0.7.2
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/dist/engine.d.ts +62 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +261 -0
- package/dist/engine.js.map +1 -0
- package/{src/index.ts → dist/index.d.ts} +5 -27
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/override.d.ts +80 -0
- package/dist/override.d.ts.map +1 -0
- package/dist/override.js +127 -0
- package/dist/override.js.map +1 -0
- package/dist/scanner.d.ts +53 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +115 -0
- package/dist/scanner.js.map +1 -0
- package/dist/supply-chain.d.ts +59 -0
- package/dist/supply-chain.d.ts.map +1 -0
- package/dist/supply-chain.js +257 -0
- package/dist/supply-chain.js.map +1 -0
- package/package.json +17 -4
- package/src/engine.ts +0 -322
- package/src/override.ts +0 -168
- package/src/scanner.ts +0 -169
- package/src/supply-chain.ts +0 -316
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus Package Scanner — reads package.json and coordinates audits.
|
|
3
|
+
*
|
|
4
|
+
* Combines:
|
|
5
|
+
* - CVE scanning via OSV (engine.ts)
|
|
6
|
+
* - Supply chain risk via npm registry (supply-chain.ts)
|
|
7
|
+
* - Override policy validation (override.ts)
|
|
8
|
+
*
|
|
9
|
+
* Entry point for both the CLI and the Vite plugin.
|
|
10
|
+
*/
|
|
11
|
+
import { filterVulnerable, type AuditResult, type VulnSeverity } from './engine.js';
|
|
12
|
+
import { type SupplyChainResult } from './supply-chain.js';
|
|
13
|
+
import { formatOverrides, type AllowVulnerableConfig } from './override.js';
|
|
14
|
+
export type { AuditResult, VulnSeverity, SupplyChainResult, AllowVulnerableConfig };
|
|
15
|
+
export { filterVulnerable };
|
|
16
|
+
export interface ScanOptions {
|
|
17
|
+
root: string;
|
|
18
|
+
/** Include devDependencies in the scan (default: false) */
|
|
19
|
+
includeDev?: boolean;
|
|
20
|
+
/** Supply chain guard (default: true) */
|
|
21
|
+
supplyChain?: boolean;
|
|
22
|
+
/** Override exceptions from nexus.config.ts security.allowVulnerable */
|
|
23
|
+
allowVulnerable?: AllowVulnerableConfig;
|
|
24
|
+
/**
|
|
25
|
+
* If true, critical CVEs that are not overridden will throw (for build-time blocking).
|
|
26
|
+
* If false, they are reported but don't throw.
|
|
27
|
+
*/
|
|
28
|
+
failOnCritical?: boolean;
|
|
29
|
+
/** Minimum severity to report (default: 'low') */
|
|
30
|
+
minSeverity?: VulnSeverity;
|
|
31
|
+
}
|
|
32
|
+
export interface ScanResult {
|
|
33
|
+
scannedPackages: number;
|
|
34
|
+
vulnerable: AuditResult[];
|
|
35
|
+
supplyChain: Map<string, SupplyChainResult>;
|
|
36
|
+
overrideStatus: ReturnType<typeof formatOverrides>;
|
|
37
|
+
blockedPackages: string[];
|
|
38
|
+
durationMs: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Full dependency scan: CVE + supply chain + override validation.
|
|
42
|
+
* This is the core function called by both `nexus audit` and the Vite plugin.
|
|
43
|
+
*/
|
|
44
|
+
export declare function scanProject(opts: ScanOptions): Promise<ScanResult>;
|
|
45
|
+
export declare class NexusSecurityError extends Error {
|
|
46
|
+
readonly blockedPackages: string[];
|
|
47
|
+
readonly vulnerable: AuditResult[];
|
|
48
|
+
constructor(message: string, blockedPackages: string[], vulnerable: AuditResult[]);
|
|
49
|
+
}
|
|
50
|
+
export { auditPackage } from './engine.js';
|
|
51
|
+
export { checkSupplyChain } from './supply-chain.js';
|
|
52
|
+
export { validateOverride, findOverride } from './override.js';
|
|
53
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAqB,gBAAgB,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACvG,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAuC,mBAAmB,CAAC;AAC/G,OAAO,EAAkC,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE5G,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAI5B,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAkB,MAAM,CAAC;IAC7B,2DAA2D;IAC3D,UAAU,CAAC,EAAW,OAAO,CAAC;IAC9B,yCAAyC;IACzC,WAAW,CAAC,EAAU,OAAO,CAAC;IAC9B,wEAAwE;IACxE,eAAe,CAAC,EAAM,qBAAqB,CAAC;IAC5C;;;OAGG;IACH,cAAc,CAAC,EAAO,OAAO,CAAC;IAC9B,kDAAkD;IAClD,WAAW,CAAC,EAAU,YAAY,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAK,MAAM,CAAC;IAC3B,UAAU,EAAU,WAAW,EAAE,CAAC;IAClC,WAAW,EAAS,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACnD,cAAc,EAAM,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;IACvD,eAAe,EAAK,MAAM,EAAE,CAAC;IAC7B,UAAU,EAAU,MAAM,CAAC;CAC5B;AAID;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA8FxE;AAID,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,eAAe,EAAE,MAAM,EAAE;aACzB,UAAU,EAAE,WAAW,EAAE;gBAFzC,OAAO,EAAE,MAAM,EACC,eAAe,EAAE,MAAM,EAAE,EACzB,UAAU,EAAE,WAAW,EAAE;CAK5C;AAID,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/scanner.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus Package Scanner — reads package.json and coordinates audits.
|
|
3
|
+
*
|
|
4
|
+
* Combines:
|
|
5
|
+
* - CVE scanning via OSV (engine.ts)
|
|
6
|
+
* - Supply chain risk via npm registry (supply-chain.ts)
|
|
7
|
+
* - Override policy validation (override.ts)
|
|
8
|
+
*
|
|
9
|
+
* Entry point for both the CLI and the Vite plugin.
|
|
10
|
+
*/
|
|
11
|
+
import { readFile } from 'node:fs/promises';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { auditDependencies, filterVulnerable } from './engine.js';
|
|
14
|
+
import { auditSupplyChain } from './supply-chain.js';
|
|
15
|
+
import { findOverride, formatOverrides } from './override.js';
|
|
16
|
+
export { filterVulnerable };
|
|
17
|
+
// ── Main scanner ──────────────────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Full dependency scan: CVE + supply chain + override validation.
|
|
20
|
+
* This is the core function called by both `nexus audit` and the Vite plugin.
|
|
21
|
+
*/
|
|
22
|
+
export async function scanProject(opts) {
|
|
23
|
+
const t0 = Date.now();
|
|
24
|
+
// Read package.json
|
|
25
|
+
const pkgPath = join(opts.root, 'package.json');
|
|
26
|
+
let pkgJson;
|
|
27
|
+
try {
|
|
28
|
+
pkgJson = JSON.parse(await readFile(pkgPath, 'utf-8'));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error(`[Nexus Audit] Cannot read package.json at ${pkgPath}`);
|
|
32
|
+
}
|
|
33
|
+
// Collect deps
|
|
34
|
+
const deps = {
|
|
35
|
+
...pkgJson.dependencies,
|
|
36
|
+
...(opts.includeDev ? pkgJson.devDependencies : {}),
|
|
37
|
+
};
|
|
38
|
+
const scannedPackages = Object.keys(deps).length;
|
|
39
|
+
// Parallel: CVE scan + supply chain scan
|
|
40
|
+
const [cveResults, scResults] = await Promise.all([
|
|
41
|
+
auditDependencies(deps),
|
|
42
|
+
opts.supplyChain !== false ? auditSupplyChain(deps) : Promise.resolve(new Map()),
|
|
43
|
+
]);
|
|
44
|
+
const vulnerable = filterVulnerable(cveResults);
|
|
45
|
+
// Override policy validation
|
|
46
|
+
const overrides = opts.allowVulnerable ?? {};
|
|
47
|
+
const overrideStats = formatOverrides(overrides);
|
|
48
|
+
const blockedPackages = [];
|
|
49
|
+
const SORDER = { critical: 0, high: 1, medium: 2, low: 3, unknown: 4 };
|
|
50
|
+
const minSev = opts.minSeverity ?? 'low';
|
|
51
|
+
for (const result of vulnerable) {
|
|
52
|
+
for (const vuln of result.vulns) {
|
|
53
|
+
if (SORDER[vuln.severity] > SORDER[minSev])
|
|
54
|
+
continue;
|
|
55
|
+
if (vuln.severity !== 'critical' && vuln.severity !== 'high')
|
|
56
|
+
continue;
|
|
57
|
+
// Check if there's a valid override
|
|
58
|
+
const overrideResult = findOverride(result.package, vuln.id, overrides)
|
|
59
|
+
?? findOverride(result.package, vuln.aliases[0] ?? '', overrides);
|
|
60
|
+
if (overrideResult?.valid) {
|
|
61
|
+
// Override is active — report but don't block
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!overrideResult || overrideResult.expired) {
|
|
65
|
+
// No override or expired → block
|
|
66
|
+
if (!blockedPackages.includes(result.package)) {
|
|
67
|
+
blockedPackages.push(result.package);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const scanResult = {
|
|
73
|
+
scannedPackages,
|
|
74
|
+
vulnerable,
|
|
75
|
+
supplyChain: scResults,
|
|
76
|
+
overrideStatus: overrideStats,
|
|
77
|
+
blockedPackages,
|
|
78
|
+
durationMs: Date.now() - t0,
|
|
79
|
+
};
|
|
80
|
+
// Throw for build-time blocking
|
|
81
|
+
if (opts.failOnCritical && blockedPackages.length > 0) {
|
|
82
|
+
const details = blockedPackages
|
|
83
|
+
.map((pkg) => {
|
|
84
|
+
const r = cveResults.get(pkg);
|
|
85
|
+
const topVuln = r?.vulns[0];
|
|
86
|
+
return topVuln
|
|
87
|
+
? ` "${pkg}" — ${topVuln.id} (${topVuln.severity.toUpperCase()}): ${topVuln.summary}`
|
|
88
|
+
: ` "${pkg}"`;
|
|
89
|
+
})
|
|
90
|
+
.join('\n');
|
|
91
|
+
throw new NexusSecurityError(`[Nexus Security] 🛑 BUILD BLOCKED — ${blockedPackages.length} critical/high CVE${blockedPackages.length > 1 ? 's' : ''} detected:\n\n` +
|
|
92
|
+
`${details}\n\n` +
|
|
93
|
+
`Options:\n` +
|
|
94
|
+
` 1. Run \`nexus fix\` to automatically update to patched versions\n` +
|
|
95
|
+
` 2. Add a time-limited override in nexus.config.ts (security.allowVulnerable)\n` +
|
|
96
|
+
` 3. Run \`nexus audit\` for full details and suggested fixes`, blockedPackages, vulnerable);
|
|
97
|
+
}
|
|
98
|
+
return scanResult;
|
|
99
|
+
}
|
|
100
|
+
// ── Error class ───────────────────────────────────────────────────────────────
|
|
101
|
+
export class NexusSecurityError extends Error {
|
|
102
|
+
blockedPackages;
|
|
103
|
+
vulnerable;
|
|
104
|
+
constructor(message, blockedPackages, vulnerable) {
|
|
105
|
+
super(message);
|
|
106
|
+
this.blockedPackages = blockedPackages;
|
|
107
|
+
this.vulnerable = vulnerable;
|
|
108
|
+
this.name = 'NexusSecurityError';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// ── Single-package audit (for Vite plugin import hook) ───────────────────────
|
|
112
|
+
export { auditPackage } from './engine.js';
|
|
113
|
+
export { checkSupplyChain } from './supply-chain.js';
|
|
114
|
+
export { validateOverride, findOverride } from './override.js';
|
|
115
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus Supply Chain Guard.
|
|
3
|
+
*
|
|
4
|
+
* Uses the public npm registry API to detect signs of supply chain compromise:
|
|
5
|
+
*
|
|
6
|
+
* 1. SINGLE MAINTAINER — one compromised account = full package control
|
|
7
|
+
* 2. RECENT MAINTAINER CHANGE — new owner in last 90 days (account takeover pattern)
|
|
8
|
+
* 3. NEWLY PUBLISHED POPULAR NAME — typosquatting / dependency confusion
|
|
9
|
+
* 4. ABANDONED PACKAGE — no updates in 2+ years but still widely imported
|
|
10
|
+
* 5. RAPID VERSION BUMP — many versions published in a short time (malware injection)
|
|
11
|
+
* 6. OWNER TRANSFER — package ownership changed (acquisition or takeover)
|
|
12
|
+
*
|
|
13
|
+
* What we CANNOT check (npm considers it private):
|
|
14
|
+
* - Whether individual maintainers have MFA/2FA enabled
|
|
15
|
+
* (npm Team policy requires it for popular packages as of 2022, but status is not in the API)
|
|
16
|
+
*
|
|
17
|
+
* Risk score: 0 (safe) → 100 (critical risk)
|
|
18
|
+
* Threshold: ≥60 = warn, ≥80 = block in hardened mode
|
|
19
|
+
*
|
|
20
|
+
* npm registry API:
|
|
21
|
+
* GET https://registry.npmjs.org/{package} → full metadata
|
|
22
|
+
* GET https://registry.npmjs.org/{package}/latest → latest version only
|
|
23
|
+
*/
|
|
24
|
+
export type SupplyChainRiskLevel = 'safe' | 'low' | 'medium' | 'high' | 'critical';
|
|
25
|
+
export interface SupplyChainFlag {
|
|
26
|
+
code: string;
|
|
27
|
+
title: string;
|
|
28
|
+
description: string;
|
|
29
|
+
riskPoints: number;
|
|
30
|
+
}
|
|
31
|
+
export interface SupplyChainResult {
|
|
32
|
+
package: string;
|
|
33
|
+
riskScore: number;
|
|
34
|
+
riskLevel: SupplyChainRiskLevel;
|
|
35
|
+
flags: SupplyChainFlag[];
|
|
36
|
+
maintainers: string[];
|
|
37
|
+
latestVersion: string;
|
|
38
|
+
firstPublished: string;
|
|
39
|
+
lastPublished: string;
|
|
40
|
+
totalVersions: number;
|
|
41
|
+
cached: boolean;
|
|
42
|
+
stale: boolean;
|
|
43
|
+
checkedAt: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Analyzes a package for supply chain risk signals using the npm registry.
|
|
47
|
+
*
|
|
48
|
+
* Does NOT check individual MFA status (not in npm public API).
|
|
49
|
+
* DOES check: maintainer count, age, version velocity, abandonment.
|
|
50
|
+
*/
|
|
51
|
+
export declare function checkSupplyChain(pkg: string): Promise<SupplyChainResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Checks supply chain risk for all packages in a dependency map.
|
|
54
|
+
* Returns only packages with riskLevel >= 'medium'.
|
|
55
|
+
*/
|
|
56
|
+
export declare function auditSupplyChain(deps: Record<string, string>): Promise<Map<string, SupplyChainResult>>;
|
|
57
|
+
/** Note about MFA status — shown in audit output for transparency */
|
|
58
|
+
export declare const MFA_NOTE: string;
|
|
59
|
+
//# sourceMappingURL=supply-chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supply-chain.d.ts","sourceRoot":"","sources":["../src/supply-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAYH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAS,MAAM,CAAC;IACpB,KAAK,EAAQ,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAG,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAO,MAAM,CAAC;IACrB,SAAS,EAAK,MAAM,CAAC;IACrB,SAAS,EAAK,oBAAoB,CAAC;IACnC,KAAK,EAAS,eAAe,EAAE,CAAC;IAChC,WAAW,EAAG,MAAM,EAAE,CAAC;IACvB,aAAa,EAAC,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAG,MAAM,CAAC;IACvB,aAAa,EAAG,MAAM,CAAC;IACvB,MAAM,EAAQ,OAAO,CAAC;IACtB,KAAK,EAAS,OAAO,CAAC;IACtB,SAAS,EAAK,MAAM,CAAC;CACtB;AA8KD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA2C9E;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAqBzC;AAED,qEAAqE;AACrE,eAAO,MAAM,QAAQ,QAIgC,CAAC"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus Supply Chain Guard.
|
|
3
|
+
*
|
|
4
|
+
* Uses the public npm registry API to detect signs of supply chain compromise:
|
|
5
|
+
*
|
|
6
|
+
* 1. SINGLE MAINTAINER — one compromised account = full package control
|
|
7
|
+
* 2. RECENT MAINTAINER CHANGE — new owner in last 90 days (account takeover pattern)
|
|
8
|
+
* 3. NEWLY PUBLISHED POPULAR NAME — typosquatting / dependency confusion
|
|
9
|
+
* 4. ABANDONED PACKAGE — no updates in 2+ years but still widely imported
|
|
10
|
+
* 5. RAPID VERSION BUMP — many versions published in a short time (malware injection)
|
|
11
|
+
* 6. OWNER TRANSFER — package ownership changed (acquisition or takeover)
|
|
12
|
+
*
|
|
13
|
+
* What we CANNOT check (npm considers it private):
|
|
14
|
+
* - Whether individual maintainers have MFA/2FA enabled
|
|
15
|
+
* (npm Team policy requires it for popular packages as of 2022, but status is not in the API)
|
|
16
|
+
*
|
|
17
|
+
* Risk score: 0 (safe) → 100 (critical risk)
|
|
18
|
+
* Threshold: ≥60 = warn, ≥80 = block in hardened mode
|
|
19
|
+
*
|
|
20
|
+
* npm registry API:
|
|
21
|
+
* GET https://registry.npmjs.org/{package} → full metadata
|
|
22
|
+
* GET https://registry.npmjs.org/{package}/latest → latest version only
|
|
23
|
+
*/
|
|
24
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
25
|
+
import { join } from 'node:path';
|
|
26
|
+
import { homedir } from 'node:os';
|
|
27
|
+
const REGISTRY = 'https://registry.npmjs.org';
|
|
28
|
+
const CACHE_DIR = join(homedir(), '.nexus', 'cache', 'npm-meta');
|
|
29
|
+
const CACHE_TTL_MS = 6 * 60 * 60 * 1_000; // 6h (changes more frequently than CVEs)
|
|
30
|
+
// ── Cache ─────────────────────────────────────────────────────────────────────
|
|
31
|
+
async function ensureDir() {
|
|
32
|
+
try {
|
|
33
|
+
await mkdir(CACHE_DIR, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
catch { /* exists */ }
|
|
36
|
+
}
|
|
37
|
+
function cacheKey(pkg) {
|
|
38
|
+
return pkg.replace(/\//g, '__').replace(/@/g, '_at_');
|
|
39
|
+
}
|
|
40
|
+
async function readNpmCache(pkg) {
|
|
41
|
+
try {
|
|
42
|
+
const raw = await readFile(join(CACHE_DIR, `${cacheKey(pkg)}.json`), 'utf-8');
|
|
43
|
+
return JSON.parse(raw);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function writeNpmCache(pkg, result) {
|
|
50
|
+
await ensureDir();
|
|
51
|
+
try {
|
|
52
|
+
await writeFile(join(CACHE_DIR, `${cacheKey(pkg)}.json`), JSON.stringify({ result, expiresAt: Date.now() + CACHE_TTL_MS }, null, 2));
|
|
53
|
+
}
|
|
54
|
+
catch { /* non-fatal */ }
|
|
55
|
+
}
|
|
56
|
+
// ── Fetch ─────────────────────────────────────────────────────────────────────
|
|
57
|
+
async function fetchNpmMeta(pkg) {
|
|
58
|
+
const controller = new AbortController();
|
|
59
|
+
const timeout = setTimeout(() => controller.abort(), 10_000);
|
|
60
|
+
try {
|
|
61
|
+
const res = await fetch(`${REGISTRY}/${encodeURIComponent(pkg)}`, {
|
|
62
|
+
headers: { accept: 'application/vnd.npm.install-v1+json, application/json' },
|
|
63
|
+
signal: controller.signal,
|
|
64
|
+
});
|
|
65
|
+
if (!res.ok)
|
|
66
|
+
return null;
|
|
67
|
+
return await res.json();
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
clearTimeout(timeout);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// ── Risk analysis ─────────────────────────────────────────────────────────────
|
|
77
|
+
function daysBetween(a, b = new Date().toISOString()) {
|
|
78
|
+
return Math.floor((new Date(b).getTime() - new Date(a).getTime()) / (1000 * 60 * 60 * 24));
|
|
79
|
+
}
|
|
80
|
+
function analyzeRisk(meta) {
|
|
81
|
+
const flags = [];
|
|
82
|
+
let score = 0;
|
|
83
|
+
const maintainerCount = meta.maintainers?.length ?? 0;
|
|
84
|
+
const versions = Object.keys(meta.versions ?? {});
|
|
85
|
+
const timeEntries = Object.entries(meta.time ?? {})
|
|
86
|
+
.filter(([k]) => !['created', 'modified'].includes(k))
|
|
87
|
+
.sort(([, a], [, b]) => new Date(a).getTime() - new Date(b).getTime());
|
|
88
|
+
const firstPublished = meta.time['created'] ?? timeEntries[0]?.[1] ?? '';
|
|
89
|
+
const lastPublished = meta.time['modified'] ?? timeEntries[timeEntries.length - 1]?.[1] ?? '';
|
|
90
|
+
const daysOld = firstPublished ? daysBetween(firstPublished) : 0;
|
|
91
|
+
const daysSinceUpdate = lastPublished ? daysBetween(lastPublished) : 0;
|
|
92
|
+
// ① Single maintainer
|
|
93
|
+
if (maintainerCount === 1) {
|
|
94
|
+
const pts = 25;
|
|
95
|
+
score += pts;
|
|
96
|
+
flags.push({
|
|
97
|
+
code: 'SINGLE_MAINTAINER',
|
|
98
|
+
title: 'Single maintainer',
|
|
99
|
+
description: `This package has only 1 maintainer. A compromised account means full control over all releases.`,
|
|
100
|
+
riskPoints: pts,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
else if (maintainerCount === 0) {
|
|
104
|
+
const pts = 35;
|
|
105
|
+
score += pts;
|
|
106
|
+
flags.push({
|
|
107
|
+
code: 'NO_MAINTAINER',
|
|
108
|
+
title: 'No maintainers listed',
|
|
109
|
+
description: 'No maintainers found in registry metadata — package may be abandoned or orphaned.',
|
|
110
|
+
riskPoints: pts,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// ② Recently created (< 30 days old) — typosquatting / dependency confusion window
|
|
114
|
+
if (daysOld < 30 && daysOld > 0) {
|
|
115
|
+
const pts = 30;
|
|
116
|
+
score += pts;
|
|
117
|
+
flags.push({
|
|
118
|
+
code: 'NEWLY_PUBLISHED',
|
|
119
|
+
title: `Published ${daysOld} day${daysOld === 1 ? '' : 's'} ago`,
|
|
120
|
+
description: 'Very new packages are high-risk for typosquatting and dependency confusion attacks. Verify the name carefully.',
|
|
121
|
+
riskPoints: pts,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
// ③ Abandoned — last update > 2 years
|
|
125
|
+
if (daysSinceUpdate > 730 && versions.length > 0) {
|
|
126
|
+
const years = (daysSinceUpdate / 365).toFixed(1);
|
|
127
|
+
const pts = 20;
|
|
128
|
+
score += pts;
|
|
129
|
+
flags.push({
|
|
130
|
+
code: 'ABANDONED',
|
|
131
|
+
title: `Not updated in ${years} years`,
|
|
132
|
+
description: 'Abandoned packages accumulate unpatched CVEs and may not work with current Node.js versions.',
|
|
133
|
+
riskPoints: pts,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
// ④ Rapid version publishing — many versions in a short window (injection pattern)
|
|
137
|
+
const recentVersions = timeEntries.filter(([, ts]) => daysBetween(ts) < 7);
|
|
138
|
+
if (recentVersions.length >= 5) {
|
|
139
|
+
const pts = 35;
|
|
140
|
+
score += pts;
|
|
141
|
+
flags.push({
|
|
142
|
+
code: 'RAPID_VERSIONS',
|
|
143
|
+
title: `${recentVersions.length} versions published in the last 7 days`,
|
|
144
|
+
description: 'Rapid version publishing is a known pattern for malware injection — attackers publish many versions to slip through automated scanners.',
|
|
145
|
+
riskPoints: pts,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
// ⑤ Recent maintainer churn — if many versions published very recently from fresh pkg
|
|
149
|
+
const last30DayVersions = timeEntries.filter(([, ts]) => daysBetween(ts) < 30).length;
|
|
150
|
+
if (daysOld < 180 && last30DayVersions > 10) {
|
|
151
|
+
const pts = 20;
|
|
152
|
+
score += pts;
|
|
153
|
+
flags.push({
|
|
154
|
+
code: 'OWNERSHIP_CHURN',
|
|
155
|
+
title: 'High version churn on a new package',
|
|
156
|
+
description: `${last30DayVersions} versions in the last 30 days on a package less than 6 months old — possible account takeover or automated malware distribution.`,
|
|
157
|
+
riskPoints: pts,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
// ⑥ Very few total versions for a package > 1 year old (abandoned, low quality)
|
|
161
|
+
if (versions.length <= 2 && daysOld > 365) {
|
|
162
|
+
const pts = 10;
|
|
163
|
+
score += pts;
|
|
164
|
+
flags.push({
|
|
165
|
+
code: 'LOW_ACTIVITY',
|
|
166
|
+
title: 'Very few versions for an old package',
|
|
167
|
+
description: 'Package has barely been maintained. May have unaddressed bugs or security issues.',
|
|
168
|
+
riskPoints: pts,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return { flags, score: Math.min(100, score) };
|
|
172
|
+
}
|
|
173
|
+
function scoreToLevel(score) {
|
|
174
|
+
if (score >= 80)
|
|
175
|
+
return 'critical';
|
|
176
|
+
if (score >= 60)
|
|
177
|
+
return 'high';
|
|
178
|
+
if (score >= 35)
|
|
179
|
+
return 'medium';
|
|
180
|
+
if (score >= 15)
|
|
181
|
+
return 'low';
|
|
182
|
+
return 'safe';
|
|
183
|
+
}
|
|
184
|
+
// ── Public API ────────────────────────────────────────────────────────────────
|
|
185
|
+
/**
|
|
186
|
+
* Analyzes a package for supply chain risk signals using the npm registry.
|
|
187
|
+
*
|
|
188
|
+
* Does NOT check individual MFA status (not in npm public API).
|
|
189
|
+
* DOES check: maintainer count, age, version velocity, abandonment.
|
|
190
|
+
*/
|
|
191
|
+
export async function checkSupplyChain(pkg) {
|
|
192
|
+
const cached = await readNpmCache(pkg);
|
|
193
|
+
const now = Date.now();
|
|
194
|
+
if (cached && now < cached.expiresAt) {
|
|
195
|
+
return { ...cached.result, cached: true, stale: false };
|
|
196
|
+
}
|
|
197
|
+
const meta = await fetchNpmMeta(pkg);
|
|
198
|
+
if (!meta) {
|
|
199
|
+
if (cached)
|
|
200
|
+
return { ...cached.result, cached: true, stale: true };
|
|
201
|
+
return {
|
|
202
|
+
package: pkg, riskScore: 0, riskLevel: 'safe', flags: [],
|
|
203
|
+
maintainers: [], latestVersion: 'unknown',
|
|
204
|
+
firstPublished: '', lastPublished: '', totalVersions: 0,
|
|
205
|
+
cached: false, stale: false, checkedAt: now,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const { flags, score } = analyzeRisk(meta);
|
|
209
|
+
const versions = Object.keys(meta.versions ?? {});
|
|
210
|
+
const timeEntries = Object.entries(meta.time ?? {})
|
|
211
|
+
.filter(([k]) => !['created', 'modified'].includes(k))
|
|
212
|
+
.sort(([, a], [, b]) => new Date(a).getTime() - new Date(b).getTime());
|
|
213
|
+
const result = {
|
|
214
|
+
package: meta.name ?? pkg,
|
|
215
|
+
riskScore: score,
|
|
216
|
+
riskLevel: scoreToLevel(score),
|
|
217
|
+
flags,
|
|
218
|
+
maintainers: (meta.maintainers ?? []).map((m) => m.name),
|
|
219
|
+
latestVersion: meta['dist-tags']?.latest ?? versions[versions.length - 1] ?? 'unknown',
|
|
220
|
+
firstPublished: meta.time['created'] ?? timeEntries[0]?.[1] ?? '',
|
|
221
|
+
lastPublished: meta.time['modified'] ?? timeEntries[timeEntries.length - 1]?.[1] ?? '',
|
|
222
|
+
totalVersions: versions.length,
|
|
223
|
+
cached: false,
|
|
224
|
+
stale: false,
|
|
225
|
+
checkedAt: now,
|
|
226
|
+
};
|
|
227
|
+
await writeNpmCache(pkg, result);
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Checks supply chain risk for all packages in a dependency map.
|
|
232
|
+
* Returns only packages with riskLevel >= 'medium'.
|
|
233
|
+
*/
|
|
234
|
+
export async function auditSupplyChain(deps) {
|
|
235
|
+
const results = new Map();
|
|
236
|
+
const packages = Object.keys(deps);
|
|
237
|
+
const BATCH = 8;
|
|
238
|
+
for (let i = 0; i < packages.length; i += BATCH) {
|
|
239
|
+
const batch = packages.slice(i, i + BATCH);
|
|
240
|
+
const settled = await Promise.allSettled(batch.map(async (pkg) => {
|
|
241
|
+
const result = await checkSupplyChain(pkg);
|
|
242
|
+
return [pkg, result];
|
|
243
|
+
}));
|
|
244
|
+
for (const s of settled) {
|
|
245
|
+
if (s.status === 'fulfilled' && s.value[1].riskLevel !== 'safe') {
|
|
246
|
+
results.set(s.value[0], s.value[1]);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return results;
|
|
251
|
+
}
|
|
252
|
+
/** Note about MFA status — shown in audit output for transparency */
|
|
253
|
+
export const MFA_NOTE = 'npm requires MFA for maintainers of packages with >500 weekly downloads as of 2022, ' +
|
|
254
|
+
'but individual MFA status is not publicly exposed by the registry API. ' +
|
|
255
|
+
'Use `npm access list collaborators {package}` with appropriate permissions ' +
|
|
256
|
+
'to view maintainer details for your own packages.';
|
|
257
|
+
//# sourceMappingURL=supply-chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supply-chain.js","sourceRoot":"","sources":["../src/supply-chain.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexus_js/audit",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Nexus Dependency Auditor — OSV CVE scanning, offline cache, supply chain risk analysis, and build-time blocking",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
|
-
".":
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
9
13
|
},
|
|
10
14
|
"keywords": [
|
|
11
15
|
"nexus",
|
|
@@ -32,12 +36,21 @@
|
|
|
32
36
|
"bugs": {
|
|
33
37
|
"url": "https://github.com/bierfor/nexus/issues"
|
|
34
38
|
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^22.0.0",
|
|
41
|
+
"typescript": "^5.5.0"
|
|
42
|
+
},
|
|
35
43
|
"files": [
|
|
36
|
-
"
|
|
44
|
+
"dist",
|
|
37
45
|
"README.md"
|
|
38
46
|
],
|
|
39
47
|
"publishConfig": {
|
|
40
48
|
"access": "public",
|
|
41
49
|
"registry": "https://registry.npmjs.org/"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc -p tsconfig.json",
|
|
53
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
54
|
+
"clean": "rm -rf dist"
|
|
42
55
|
}
|
|
43
56
|
}
|