@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.
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Nexus Audit Engine — CVE Database via OSV (Open Source Vulnerabilities).
3
+ *
4
+ * Uses the free, open Google OSV API (https://osv.dev) — no API key required.
5
+ * Responses are cached locally in ~/.nexus/cache/ for offline operation.
6
+ *
7
+ * API reference: https://google.github.io/osv.dev/api/
8
+ *
9
+ * Cache strategy:
10
+ * - Queries are cached per package@version for 24h (TTL configurable)
11
+ * - On offline: stale cache is used transparently (no error)
12
+ * - Cache location: ~/.nexus/cache/osv/{pkg-name}.json
13
+ *
14
+ * OSV severity mapping to Nexus levels:
15
+ * CRITICAL → critical (CVSS ≥ 9.0 or explicit CRITICAL)
16
+ * HIGH → high (CVSS 7.0–8.9)
17
+ * MEDIUM → medium (CVSS 4.0–6.9)
18
+ * LOW → low (CVSS < 4.0)
19
+ */
20
+ export type VulnSeverity = 'critical' | 'high' | 'medium' | 'low' | 'unknown';
21
+ export interface Vulnerability {
22
+ id: string;
23
+ summary: string;
24
+ severity: VulnSeverity;
25
+ cvss?: number | undefined;
26
+ aliases: string[];
27
+ affectedVersions: string;
28
+ fixedIn?: string | undefined;
29
+ references: string[];
30
+ published: string;
31
+ }
32
+ export interface AuditResult {
33
+ package: string;
34
+ version: string;
35
+ status: 'safe' | 'vulnerable' | 'unknown';
36
+ vulns: Vulnerability[];
37
+ /** True if result came from local cache */
38
+ cached: boolean;
39
+ /** True if result is stale (TTL expired) but used because offline */
40
+ stale: boolean;
41
+ checkedAt: number;
42
+ }
43
+ /**
44
+ * Audits a single package for known CVEs using the OSV database.
45
+ * Results are cached locally for 24h.
46
+ *
47
+ * @param pkg Package name (e.g. 'lodash' or '@angular/core')
48
+ * @param version Specific version to check (e.g. '4.17.20'). If omitted, checks all versions.
49
+ */
50
+ export declare function auditPackage(pkg: string, version?: string): Promise<AuditResult>;
51
+ /**
52
+ * Audits all dependencies in a package.json.
53
+ * Runs queries in parallel (max 6 concurrent) to avoid rate limiting.
54
+ */
55
+ export declare function auditDependencies(deps: Record<string, string>): Promise<Map<string, AuditResult>>;
56
+ /** Returns only vulnerable packages, sorted by severity. */
57
+ export declare function filterVulnerable(results: Map<string, AuditResult>): AuditResult[];
58
+ /** Invalidates the local cache for a specific package (forces re-fetch). */
59
+ export declare function invalidateCache(pkg: string): Promise<void>;
60
+ /** Clears the entire OSV cache (all packages). */
61
+ export declare function clearCache(): Promise<void>;
62
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAYH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAE9E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAgB,MAAM,CAAC;IACzB,OAAO,EAAW,MAAM,CAAC;IACzB,QAAQ,EAAU,YAAY,CAAC;IAC/B,IAAI,CAAC,EAAa,MAAM,GAAG,SAAS,CAAC;IACrC,OAAO,EAAW,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAU,MAAM,GAAG,SAAS,CAAC;IACrC,UAAU,EAAQ,MAAM,EAAE,CAAC;IAC3B,SAAS,EAAS,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAM,MAAM,CAAC;IACpB,OAAO,EAAM,MAAM,CAAC;IACpB,MAAM,EAAO,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAC/C,KAAK,EAAQ,aAAa,EAAE,CAAC;IAC7B,2CAA2C;IAC3C,MAAM,EAAO,OAAO,CAAC;IACrB,qEAAqE;IACrE,KAAK,EAAQ,OAAO,CAAC;IACrB,SAAS,EAAI,MAAM,CAAC;CACrB;AA+ID;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA0DtF;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAuBnC;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,WAAW,EAAE,CASjF;AAED,4EAA4E;AAC5E,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhE;AAED,kDAAkD;AAClD,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhD"}
package/dist/engine.js ADDED
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Nexus Audit Engine — CVE Database via OSV (Open Source Vulnerabilities).
3
+ *
4
+ * Uses the free, open Google OSV API (https://osv.dev) — no API key required.
5
+ * Responses are cached locally in ~/.nexus/cache/ for offline operation.
6
+ *
7
+ * API reference: https://google.github.io/osv.dev/api/
8
+ *
9
+ * Cache strategy:
10
+ * - Queries are cached per package@version for 24h (TTL configurable)
11
+ * - On offline: stale cache is used transparently (no error)
12
+ * - Cache location: ~/.nexus/cache/osv/{pkg-name}.json
13
+ *
14
+ * OSV severity mapping to Nexus levels:
15
+ * CRITICAL → critical (CVSS ≥ 9.0 or explicit CRITICAL)
16
+ * HIGH → high (CVSS 7.0–8.9)
17
+ * MEDIUM → medium (CVSS 4.0–6.9)
18
+ * LOW → low (CVSS < 4.0)
19
+ */
20
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
21
+ import { join } from 'node:path';
22
+ import { homedir } from 'node:os';
23
+ const OSV_API = 'https://api.osv.dev/v1/query';
24
+ const CACHE_DIR = join(homedir(), '.nexus', 'cache', 'osv');
25
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1_000; // 24h
26
+ // ── Cache helpers ─────────────────────────────────────────────────────────────
27
+ async function ensureCacheDir() {
28
+ try {
29
+ await mkdir(CACHE_DIR, { recursive: true });
30
+ }
31
+ catch { /* already exists */ }
32
+ }
33
+ function cacheKey(pkg) {
34
+ return pkg.replace(/\//g, '__').replace(/@/g, '_at_');
35
+ }
36
+ async function readCache(pkg) {
37
+ try {
38
+ const raw = await readFile(join(CACHE_DIR, `${cacheKey(pkg)}.json`), 'utf-8');
39
+ return JSON.parse(raw);
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ async function writeCache(pkg, entry) {
46
+ await ensureCacheDir();
47
+ try {
48
+ await writeFile(join(CACHE_DIR, `${cacheKey(pkg)}.json`), JSON.stringify(entry, null, 2));
49
+ }
50
+ catch { /* cache write failure is non-fatal */ }
51
+ }
52
+ // ── OSV API ───────────────────────────────────────────────────────────────────
53
+ function parseSeverity(vuln) {
54
+ const severityBlock = vuln.severity ?? [];
55
+ // Look for CVSS v3 score first
56
+ for (const s of severityBlock) {
57
+ if (s.type === 'CVSS_V3' || s.type === 'CVSS_V4') {
58
+ // Extract numeric score from vector string (e.g. "CVSS:3.1/AV:N/AC:L/...")
59
+ // OSV also sometimes provides the numeric score directly
60
+ const scoreMatch = s.score.match(/^(\d+\.\d+)$/) ??
61
+ s.score.match(/\/(\d+\.\d+)$/);
62
+ const score = scoreMatch ? parseFloat(scoreMatch[1] ?? '0') : 0;
63
+ let sev = 'unknown';
64
+ if (score >= 9.0)
65
+ sev = 'critical';
66
+ else if (score >= 7.0)
67
+ sev = 'high';
68
+ else if (score >= 4.0)
69
+ sev = 'medium';
70
+ else if (score > 0)
71
+ sev = 'low';
72
+ return { severity: sev, cvss: score };
73
+ }
74
+ }
75
+ // Fall back to explicit severity labels in the ID
76
+ const id = vuln.id.toUpperCase();
77
+ if (id.includes('CRITICAL'))
78
+ return { severity: 'critical' };
79
+ if (id.includes('HIGH'))
80
+ return { severity: 'high' };
81
+ if (id.includes('MEDIUM'))
82
+ return { severity: 'medium' };
83
+ if (id.includes('LOW'))
84
+ return { severity: 'low' };
85
+ return { severity: 'unknown' };
86
+ }
87
+ function parseFixedVersion(vuln) {
88
+ for (const affected of vuln.affected ?? []) {
89
+ for (const range of affected.ranges ?? []) {
90
+ for (const event of range.events ?? []) {
91
+ if (event.fixed)
92
+ return event.fixed;
93
+ }
94
+ }
95
+ }
96
+ return undefined;
97
+ }
98
+ function parseAffectedVersions(vuln) {
99
+ const parts = [];
100
+ for (const affected of vuln.affected ?? []) {
101
+ for (const range of affected.ranges ?? []) {
102
+ let intro;
103
+ let fixed;
104
+ for (const event of range.events ?? []) {
105
+ if (event.introduced)
106
+ intro = event.introduced;
107
+ if (event.fixed)
108
+ fixed = event.fixed;
109
+ }
110
+ if (intro && fixed)
111
+ parts.push(`>=${intro} <${fixed}`);
112
+ else if (intro)
113
+ parts.push(`>=${intro}`);
114
+ else if (fixed)
115
+ parts.push(`<${fixed}`);
116
+ }
117
+ // Direct version list
118
+ if (affected.versions?.length) {
119
+ parts.push(affected.versions.slice(0, 5).join(', ') + (affected.versions.length > 5 ? '...' : ''));
120
+ }
121
+ }
122
+ return parts.join('; ') || 'all versions';
123
+ }
124
+ async function fetchFromOSV(pkg, version) {
125
+ const body = {
126
+ package: { name: pkg, ecosystem: 'npm' },
127
+ };
128
+ if (version)
129
+ body['version'] = version;
130
+ const controller = new AbortController();
131
+ const timeout = setTimeout(() => controller.abort(), 8_000);
132
+ try {
133
+ const res = await fetch(OSV_API, {
134
+ method: 'POST',
135
+ headers: { 'content-type': 'application/json' },
136
+ body: JSON.stringify(body),
137
+ signal: controller.signal,
138
+ });
139
+ if (!res.ok)
140
+ return null;
141
+ return await res.json();
142
+ }
143
+ catch {
144
+ return null; // network error — caller falls back to cache
145
+ }
146
+ finally {
147
+ clearTimeout(timeout);
148
+ }
149
+ }
150
+ // ── Public API ────────────────────────────────────────────────────────────────
151
+ /**
152
+ * Audits a single package for known CVEs using the OSV database.
153
+ * Results are cached locally for 24h.
154
+ *
155
+ * @param pkg Package name (e.g. 'lodash' or '@angular/core')
156
+ * @param version Specific version to check (e.g. '4.17.20'). If omitted, checks all versions.
157
+ */
158
+ export async function auditPackage(pkg, version) {
159
+ const cached = await readCache(pkg);
160
+ const now = Date.now();
161
+ // Fresh cache hit
162
+ if (cached && now < cached.expiresAt) {
163
+ return { ...cached.result, cached: true, stale: false };
164
+ }
165
+ // Try to fetch from OSV
166
+ const osvData = await fetchFromOSV(pkg, version);
167
+ if (!osvData) {
168
+ // Offline or API error — use stale cache if available
169
+ if (cached) {
170
+ return { ...cached.result, cached: true, stale: true };
171
+ }
172
+ // No cache at all
173
+ return {
174
+ package: pkg, version: version ?? '*',
175
+ status: 'unknown', vulns: [],
176
+ cached: false, stale: false,
177
+ checkedAt: now,
178
+ };
179
+ }
180
+ // Parse OSV response
181
+ const vulns = (osvData.vulns ?? []).map((v) => {
182
+ const { severity, cvss } = parseSeverity(v);
183
+ return {
184
+ id: v.id,
185
+ summary: v.summary ?? 'No summary available',
186
+ severity,
187
+ cvss,
188
+ aliases: v.aliases ?? [],
189
+ affectedVersions: parseAffectedVersions(v),
190
+ fixedIn: parseFixedVersion(v),
191
+ references: (v.references ?? []).map((r) => r.url),
192
+ published: v.published,
193
+ };
194
+ });
195
+ // Sort by severity
196
+ const SORDER = { critical: 0, high: 1, medium: 2, low: 3, unknown: 4 };
197
+ vulns.sort((a, b) => SORDER[a.severity] - SORDER[b.severity]);
198
+ const result = {
199
+ package: pkg,
200
+ version: version ?? '*',
201
+ status: vulns.length > 0 ? 'vulnerable' : 'safe',
202
+ vulns,
203
+ cached: false,
204
+ stale: false,
205
+ checkedAt: now,
206
+ };
207
+ await writeCache(pkg, { result, expiresAt: now + CACHE_TTL_MS, version: version ?? '*' });
208
+ return result;
209
+ }
210
+ /**
211
+ * Audits all dependencies in a package.json.
212
+ * Runs queries in parallel (max 6 concurrent) to avoid rate limiting.
213
+ */
214
+ export async function auditDependencies(deps) {
215
+ const results = new Map();
216
+ const entries = Object.entries(deps);
217
+ const BATCH = 6;
218
+ for (let i = 0; i < entries.length; i += BATCH) {
219
+ const batch = entries.slice(i, i + BATCH);
220
+ const settled = await Promise.allSettled(batch.map(async ([name, versionRange]) => {
221
+ // Strip semver range prefix for OSV query
222
+ const version = versionRange.replace(/^[\^~>=<]/, '').split(' ')[0];
223
+ const result = await auditPackage(name, version);
224
+ return [name, result];
225
+ }));
226
+ for (const s of settled) {
227
+ if (s.status === 'fulfilled') {
228
+ results.set(s.value[0], s.value[1]);
229
+ }
230
+ }
231
+ }
232
+ return results;
233
+ }
234
+ /** Returns only vulnerable packages, sorted by severity. */
235
+ export function filterVulnerable(results) {
236
+ const SORDER = { critical: 0, high: 1, medium: 2, low: 3, unknown: 4 };
237
+ return [...results.values()]
238
+ .filter((r) => r.status === 'vulnerable')
239
+ .sort((a, b) => {
240
+ const as = a.vulns[0]?.severity ?? 'unknown';
241
+ const bs = b.vulns[0]?.severity ?? 'unknown';
242
+ return SORDER[as] - SORDER[bs];
243
+ });
244
+ }
245
+ /** Invalidates the local cache for a specific package (forces re-fetch). */
246
+ export async function invalidateCache(pkg) {
247
+ const { unlink } = await import('node:fs/promises');
248
+ try {
249
+ await unlink(join(CACHE_DIR, `${cacheKey(pkg)}.json`));
250
+ }
251
+ catch { /* file may not exist */ }
252
+ }
253
+ /** Clears the entire OSV cache (all packages). */
254
+ export async function clearCache() {
255
+ const { rm } = await import('node:fs/promises');
256
+ try {
257
+ await rm(CACHE_DIR, { recursive: true, force: true });
258
+ }
259
+ catch { /* ignore */ }
260
+ }
261
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
@@ -9,34 +9,12 @@
9
9
  * - Build-time blocking for critical vulnerabilities
10
10
  * - `nexus fix` auto-remediation data
11
11
  */
12
-
13
- export {
14
- auditPackage,
15
- auditDependencies,
16
- filterVulnerable,
17
- invalidateCache,
18
- clearCache,
19
- } from './engine.js';
12
+ export { auditPackage, auditDependencies, filterVulnerable, invalidateCache, clearCache, } from './engine.js';
20
13
  export type { AuditResult, Vulnerability, VulnSeverity } from './engine.js';
21
-
22
- export {
23
- checkSupplyChain,
24
- auditSupplyChain,
25
- MFA_NOTE,
26
- } from './supply-chain.js';
14
+ export { checkSupplyChain, auditSupplyChain, MFA_NOTE, } from './supply-chain.js';
27
15
  export type { SupplyChainResult, SupplyChainFlag, SupplyChainRiskLevel } from './supply-chain.js';
28
-
29
- export {
30
- validateOverride,
31
- findOverride,
32
- formatOverrides,
33
- maxOverrideDate,
34
- } from './override.js';
16
+ export { validateOverride, findOverride, formatOverrides, maxOverrideDate, } from './override.js';
35
17
  export type { VulnerabilityOverride, AllowVulnerableConfig } from './override.js';
36
-
37
- export {
38
- scanProject,
39
- NexusSecurityError,
40
- auditPackage as auditSinglePackage,
41
- } from './scanner.js';
18
+ export { scanProject, NexusSecurityError, auditPackage as auditSinglePackage, } from './scanner.js';
42
19
  export type { ScanOptions, ScanResult } from './scanner.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,QAAQ,GACT,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAElG,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAElF,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,YAAY,IAAI,kBAAkB,GACnC,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @nexus_js/audit — Dependency Auditing & Supply Chain Security
3
+ *
4
+ * Provides:
5
+ * - CVE scanning via Google OSV (open, no API key)
6
+ * - Supply chain risk analysis via npm registry
7
+ * - Offline-first local cache (~/.nexus/cache/)
8
+ * - Override policy with automatic expiry
9
+ * - Build-time blocking for critical vulnerabilities
10
+ * - `nexus fix` auto-remediation data
11
+ */
12
+ export { auditPackage, auditDependencies, filterVulnerable, invalidateCache, clearCache, } from './engine.js';
13
+ export { checkSupplyChain, auditSupplyChain, MFA_NOTE, } from './supply-chain.js';
14
+ export { validateOverride, findOverride, formatOverrides, maxOverrideDate, } from './override.js';
15
+ export { scanProject, NexusSecurityError, auditPackage as auditSinglePackage, } from './scanner.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,UAAU,GACX,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,QAAQ,GACT,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,YAAY,IAAI,kBAAkB,GACnC,MAAM,cAAc,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Nexus Security Override Policy — "Ghost Wall" exceptions.
3
+ *
4
+ * Sometimes a library is vulnerable but:
5
+ * - The patch isn't yet on a stable release
6
+ * - You only use the affected function in a build-time context (never in production)
7
+ * - Your organization has an accepted risk decision documented elsewhere
8
+ *
9
+ * Overrides are explicit, time-limited exceptions that:
10
+ * 1. Require a documented reason
11
+ * 2. Expire automatically — the build fails again after the date
12
+ * 3. Are logged in every audit report
13
+ * 4. Do NOT suppress warnings (only prevent build failure)
14
+ *
15
+ * Usage in nexus.config.ts:
16
+ *
17
+ * ```ts
18
+ * import { defineNexusConfig } from '@nexus_js/core';
19
+ *
20
+ * export default defineNexusConfig({
21
+ * security: {
22
+ * hardened: true,
23
+ * allowVulnerable: {
24
+ * 'pdfkit': {
25
+ * cve: 'CVE-2024-29415',
26
+ * reason: 'Used in build-time PDF generation only. Not in the client bundle. ' +
27
+ * 'Patched version releases 2026-05-15 according to maintainer.',
28
+ * expires: '2026-06-01',
29
+ * },
30
+ * },
31
+ * },
32
+ * });
33
+ * ```
34
+ *
35
+ * After `expires`, the build fails again, forcing re-evaluation.
36
+ * If the patch is available, update the dependency. If not, extend the override with a new reason.
37
+ */
38
+ export interface VulnerabilityOverride {
39
+ /** CVE ID or OSV ID being overridden */
40
+ cve: string;
41
+ /** REQUIRED: human-readable business justification */
42
+ reason: string;
43
+ /**
44
+ * ISO date string (YYYY-MM-DD). After this date, the override expires
45
+ * and the build will fail again. Maximum: 180 days from today.
46
+ */
47
+ expires: string;
48
+ }
49
+ export type AllowVulnerableConfig = Record<string, VulnerabilityOverride>;
50
+ export interface OverrideValidation {
51
+ valid: boolean;
52
+ expired: boolean;
53
+ daysLeft: number;
54
+ message: string;
55
+ }
56
+ /**
57
+ * Validates an override at build time.
58
+ * Returns { valid: false } if expired or malformed.
59
+ */
60
+ export declare function validateOverride(pkg: string, override: VulnerabilityOverride): OverrideValidation;
61
+ /**
62
+ * Checks if a package+CVE combination is covered by an active override.
63
+ * Returns null if no override applies (build should fail on critical CVE).
64
+ */
65
+ export declare function findOverride(pkg: string, cveId: string, overrides: AllowVulnerableConfig): OverrideValidation | null;
66
+ /**
67
+ * Formats all active overrides for display in audit output.
68
+ * Groups by status: active, expiring soon, expired.
69
+ */
70
+ export declare function formatOverrides(overrides: AllowVulnerableConfig): {
71
+ active: string[];
72
+ expiringSoon: string[];
73
+ expired: string[];
74
+ };
75
+ /**
76
+ * Returns the maximum safe override duration (180 days from now).
77
+ * Overrides beyond this are rejected to prevent permanent exceptions.
78
+ */
79
+ export declare function maxOverrideDate(): string;
80
+ //# sourceMappingURL=override.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"override.d.ts","sourceRoot":"","sources":["../src/override.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,MAAM,WAAW,qBAAqB;IACpC,wCAAwC;IACxC,GAAG,EAAM,MAAM,CAAC;IAChB,sDAAsD;IACtD,MAAM,EAAG,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAE1E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAM,OAAO,CAAC;IACnB,OAAO,EAAI,OAAO,CAAC;IACnB,QAAQ,EAAG,MAAM,CAAC;IAClB,OAAO,EAAI,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAO,MAAM,EAChB,QAAQ,EAAE,qBAAqB,GAC9B,kBAAkB,CA2CpB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAO,MAAM,EAChB,KAAK,EAAK,MAAM,EAChB,SAAS,EAAE,qBAAqB,GAC/B,kBAAkB,GAAG,IAAI,CAa3B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,qBAAqB,GAC/B;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAiBjE;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAIxC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Nexus Security Override Policy — "Ghost Wall" exceptions.
3
+ *
4
+ * Sometimes a library is vulnerable but:
5
+ * - The patch isn't yet on a stable release
6
+ * - You only use the affected function in a build-time context (never in production)
7
+ * - Your organization has an accepted risk decision documented elsewhere
8
+ *
9
+ * Overrides are explicit, time-limited exceptions that:
10
+ * 1. Require a documented reason
11
+ * 2. Expire automatically — the build fails again after the date
12
+ * 3. Are logged in every audit report
13
+ * 4. Do NOT suppress warnings (only prevent build failure)
14
+ *
15
+ * Usage in nexus.config.ts:
16
+ *
17
+ * ```ts
18
+ * import { defineNexusConfig } from '@nexus_js/core';
19
+ *
20
+ * export default defineNexusConfig({
21
+ * security: {
22
+ * hardened: true,
23
+ * allowVulnerable: {
24
+ * 'pdfkit': {
25
+ * cve: 'CVE-2024-29415',
26
+ * reason: 'Used in build-time PDF generation only. Not in the client bundle. ' +
27
+ * 'Patched version releases 2026-05-15 according to maintainer.',
28
+ * expires: '2026-06-01',
29
+ * },
30
+ * },
31
+ * },
32
+ * });
33
+ * ```
34
+ *
35
+ * After `expires`, the build fails again, forcing re-evaluation.
36
+ * If the patch is available, update the dependency. If not, extend the override with a new reason.
37
+ */
38
+ /**
39
+ * Validates an override at build time.
40
+ * Returns { valid: false } if expired or malformed.
41
+ */
42
+ export function validateOverride(pkg, override) {
43
+ const expiry = new Date(override.expires);
44
+ if (isNaN(expiry.getTime())) {
45
+ return {
46
+ valid: false,
47
+ expired: false,
48
+ daysLeft: 0,
49
+ message: `[Nexus Security] Override for "${pkg}" has an invalid expiry date: "${override.expires}". Use YYYY-MM-DD format.`,
50
+ };
51
+ }
52
+ const now = new Date();
53
+ const daysLeft = Math.ceil((expiry.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
54
+ const expired = daysLeft <= 0;
55
+ if (expired) {
56
+ return {
57
+ valid: false,
58
+ expired: true,
59
+ daysLeft: 0,
60
+ message: `[Nexus Security] ⛔ Override for "${pkg}" (${override.cve}) EXPIRED on ${override.expires}.\n` +
61
+ ` Original reason: "${override.reason}"\n` +
62
+ ` The vulnerability must now be addressed. Options:\n` +
63
+ ` 1. Update "${pkg}" to a patched version\n` +
64
+ ` 2. Replace "${pkg}" with a safe alternative\n` +
65
+ ` 3. Extend the override with a new expiry date (requires fresh justification)`,
66
+ };
67
+ }
68
+ // Warn when approaching expiry
69
+ const warningDays = 14;
70
+ const warning = daysLeft <= warningDays
71
+ ? `\n ⚠️ Override for "${pkg}" expires in ${daysLeft} day${daysLeft === 1 ? '' : 's'} (${override.expires}).`
72
+ : '';
73
+ return {
74
+ valid: true,
75
+ expired: false,
76
+ daysLeft,
77
+ message: `[Nexus Security] ⚠️ OVERRIDE ACTIVE for "${pkg}" (${override.cve}).${warning}\n Reason: "${override.reason}"`,
78
+ };
79
+ }
80
+ /**
81
+ * Checks if a package+CVE combination is covered by an active override.
82
+ * Returns null if no override applies (build should fail on critical CVE).
83
+ */
84
+ export function findOverride(pkg, cveId, overrides) {
85
+ const override = overrides[pkg];
86
+ if (!override)
87
+ return null;
88
+ // Check if the CVE matches (direct or alias)
89
+ const configCve = override.cve.toUpperCase().trim();
90
+ const queryCve = cveId.toUpperCase().trim();
91
+ if (configCve !== queryCve && !queryCve.includes(configCve) && !configCve.includes(queryCve)) {
92
+ return null;
93
+ }
94
+ return validateOverride(pkg, override);
95
+ }
96
+ /**
97
+ * Formats all active overrides for display in audit output.
98
+ * Groups by status: active, expiring soon, expired.
99
+ */
100
+ export function formatOverrides(overrides) {
101
+ const active = [];
102
+ const expiringSoon = [];
103
+ const expired = [];
104
+ for (const [pkg, override] of Object.entries(overrides)) {
105
+ const v = validateOverride(pkg, override);
106
+ if (v.expired) {
107
+ expired.push(`${pkg} (${override.cve}) — expired ${override.expires}`);
108
+ }
109
+ else if (v.daysLeft <= 14) {
110
+ expiringSoon.push(`${pkg} (${override.cve}) — expires in ${v.daysLeft} days`);
111
+ }
112
+ else {
113
+ active.push(`${pkg} (${override.cve}) — ${v.daysLeft} days left`);
114
+ }
115
+ }
116
+ return { active, expiringSoon, expired };
117
+ }
118
+ /**
119
+ * Returns the maximum safe override duration (180 days from now).
120
+ * Overrides beyond this are rejected to prevent permanent exceptions.
121
+ */
122
+ export function maxOverrideDate() {
123
+ const d = new Date();
124
+ d.setDate(d.getDate() + 180);
125
+ return d.toISOString().split('T')[0];
126
+ }
127
+ //# sourceMappingURL=override.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"override.js","sourceRoot":"","sources":["../src/override.ts"],"names":[],"mappings":"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"}