@tractorcow/beefup 0.0.0 → 1.0.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/LICENSE +15 -0
- package/README.md +108 -0
- package/dist/__tests__/with-safe-chain-stubs.d.ts +5 -0
- package/dist/__tests__/with-safe-chain-stubs.js +25 -0
- package/dist/__tests__/with-safe-chain-stubs.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +6 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/args.d.ts +18 -0
- package/dist/cli/args.js +88 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/main.d.ts +4 -0
- package/dist/cli/main.js +81 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/commands/accept.d.ts +16 -0
- package/dist/commands/accept.js +47 -0
- package/dist/commands/accept.js.map +1 -0
- package/dist/commands/report.d.ts +19 -0
- package/dist/commands/report.js +151 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/stage.d.ts +16 -0
- package/dist/commands/stage.js +60 -0
- package/dist/commands/stage.js.map +1 -0
- package/dist/config/load.d.ts +6 -0
- package/dist/config/load.js +103 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/types.d.ts +75 -0
- package/dist/config/types.js +68 -0
- package/dist/config/types.js.map +1 -0
- package/dist/diff/diff.d.ts +21 -0
- package/dist/diff/diff.js +132 -0
- package/dist/diff/diff.js.map +1 -0
- package/dist/diff/group.d.ts +5 -0
- package/dist/diff/group.js +24 -0
- package/dist/diff/group.js.map +1 -0
- package/dist/diff/types.d.ts +37 -0
- package/dist/diff/types.js +7 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -0
- package/dist/fsutil.d.ts +20 -0
- package/dist/fsutil.js +43 -0
- package/dist/fsutil.js.map +1 -0
- package/dist/lockfile/locked.d.ts +9 -0
- package/dist/lockfile/locked.js +15 -0
- package/dist/lockfile/locked.js.map +1 -0
- package/dist/lockfile/npm.d.ts +15 -0
- package/dist/lockfile/npm.js +152 -0
- package/dist/lockfile/npm.js.map +1 -0
- package/dist/lockfile/pnpm.d.ts +27 -0
- package/dist/lockfile/pnpm.js +155 -0
- package/dist/lockfile/pnpm.js.map +1 -0
- package/dist/lockfile/resolve.d.ts +10 -0
- package/dist/lockfile/resolve.js +20 -0
- package/dist/lockfile/resolve.js.map +1 -0
- package/dist/lockfile/types.d.ts +49 -0
- package/dist/lockfile/types.js +2 -0
- package/dist/lockfile/types.js.map +1 -0
- package/dist/pm/cve-lite-bin.d.ts +5 -0
- package/dist/pm/cve-lite-bin.js +36 -0
- package/dist/pm/cve-lite-bin.js.map +1 -0
- package/dist/pm/install.d.ts +24 -0
- package/dist/pm/install.js +30 -0
- package/dist/pm/install.js.map +1 -0
- package/dist/pm/runner.d.ts +17 -0
- package/dist/pm/runner.js +27 -0
- package/dist/pm/runner.js.map +1 -0
- package/dist/pm/safe-chain.d.ts +17 -0
- package/dist/pm/safe-chain.js +65 -0
- package/dist/pm/safe-chain.js.map +1 -0
- package/dist/pm/update.d.ts +16 -0
- package/dist/pm/update.js +25 -0
- package/dist/pm/update.js.map +1 -0
- package/dist/policy/alignment.d.ts +13 -0
- package/dist/policy/alignment.js +171 -0
- package/dist/policy/alignment.js.map +1 -0
- package/dist/policy/evaluate.d.ts +19 -0
- package/dist/policy/evaluate.js +75 -0
- package/dist/policy/evaluate.js.map +1 -0
- package/dist/policy/overrides.d.ts +42 -0
- package/dist/policy/overrides.js +358 -0
- package/dist/policy/overrides.js.map +1 -0
- package/dist/policy/ranges.d.ts +13 -0
- package/dist/policy/ranges.js +58 -0
- package/dist/policy/ranges.js.map +1 -0
- package/dist/project/collect.d.ts +15 -0
- package/dist/project/collect.js +60 -0
- package/dist/project/collect.js.map +1 -0
- package/dist/project/detect.d.ts +5 -0
- package/dist/project/detect.js +76 -0
- package/dist/project/detect.js.map +1 -0
- package/dist/project/direct-deps.d.ts +7 -0
- package/dist/project/direct-deps.js +28 -0
- package/dist/project/direct-deps.js.map +1 -0
- package/dist/project/package-json.d.ts +20 -0
- package/dist/project/package-json.js +6 -0
- package/dist/project/package-json.js.map +1 -0
- package/dist/project/paths.d.ts +31 -0
- package/dist/project/paths.js +45 -0
- package/dist/project/paths.js.map +1 -0
- package/dist/project/types.d.ts +13 -0
- package/dist/project/types.js +6 -0
- package/dist/project/types.js.map +1 -0
- package/dist/project/workspace.d.ts +14 -0
- package/dist/project/workspace.js +80 -0
- package/dist/project/workspace.js.map +1 -0
- package/dist/report/ansi.d.ts +31 -0
- package/dist/report/ansi.js +59 -0
- package/dist/report/ansi.js.map +1 -0
- package/dist/report/html.d.ts +6 -0
- package/dist/report/html.js +260 -0
- package/dist/report/html.js.map +1 -0
- package/dist/report/markdown.d.ts +6 -0
- package/dist/report/markdown.js +234 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/report/shared.d.ts +25 -0
- package/dist/report/shared.js +32 -0
- package/dist/report/shared.js.map +1 -0
- package/dist/report/text.d.ts +10 -0
- package/dist/report/text.js +156 -0
- package/dist/report/text.js.map +1 -0
- package/dist/report/types.d.ts +20 -0
- package/dist/report/types.js +2 -0
- package/dist/report/types.js.map +1 -0
- package/dist/rewrite/constraints.d.ts +20 -0
- package/dist/rewrite/constraints.js +64 -0
- package/dist/rewrite/constraints.js.map +1 -0
- package/dist/rewrite/repin.d.ts +8 -0
- package/dist/rewrite/repin.js +28 -0
- package/dist/rewrite/repin.js.map +1 -0
- package/dist/rewrite/workspace.d.ts +14 -0
- package/dist/rewrite/workspace.js +40 -0
- package/dist/rewrite/workspace.js.map +1 -0
- package/dist/security/classify.d.ts +48 -0
- package/dist/security/classify.js +86 -0
- package/dist/security/classify.js.map +1 -0
- package/dist/security/cve-lite.d.ts +7 -0
- package/dist/security/cve-lite.js +78 -0
- package/dist/security/cve-lite.js.map +1 -0
- package/dist/security/npm-audit.d.ts +10 -0
- package/dist/security/npm-audit.js +65 -0
- package/dist/security/npm-audit.js.map +1 -0
- package/dist/security/refs.d.ts +63 -0
- package/dist/security/refs.js +218 -0
- package/dist/security/refs.js.map +1 -0
- package/dist/security/scan.d.ts +13 -0
- package/dist/security/scan.js +32 -0
- package/dist/security/scan.js.map +1 -0
- package/dist/strategy/git.d.ts +16 -0
- package/dist/strategy/git.js +92 -0
- package/dist/strategy/git.js.map +1 -0
- package/dist/strategy/index.d.ts +7 -0
- package/dist/strategy/index.js +13 -0
- package/dist/strategy/index.js.map +1 -0
- package/dist/strategy/inplace.d.ts +30 -0
- package/dist/strategy/inplace.js +77 -0
- package/dist/strategy/inplace.js.map +1 -0
- package/dist/strategy/types.d.ts +13 -0
- package/dist/strategy/types.js +2 -0
- package/dist/strategy/types.js.map +1 -0
- package/dist/strategy/worktree.d.ts +26 -0
- package/dist/strategy/worktree.js +74 -0
- package/dist/strategy/worktree.js.map +1 -0
- package/package.json +60 -4
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { UpgradeMode } from "../config/types.js";
|
|
2
|
+
import type { PackageManager } from "../project/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Rewrites dependency ranges in every workspace package.json according to upgrade mode.
|
|
5
|
+
*/
|
|
6
|
+
export declare function rewriteWorkspace(root: string, mode: UpgradeMode): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Re-pins every workspace package.json to exact versions from the given lockfile.
|
|
9
|
+
*/
|
|
10
|
+
export declare function repinWorkspace(root: string, lockfilePath: string, packageManager: PackageManager): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Joins a project root with its lockfile basename.
|
|
13
|
+
*/
|
|
14
|
+
export declare function lockfilePathFor(root: string, lockfileName: string): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { readJsonFile, writeJsonFile } from "../fsutil.js";
|
|
3
|
+
import { lockedVersionsForImporter } from "../lockfile/locked.js";
|
|
4
|
+
import { listWorkspacePackages } from "../project/workspace.js";
|
|
5
|
+
import { rewritePackageJson } from "./constraints.js";
|
|
6
|
+
import { rePinPackageJson } from "./repin.js";
|
|
7
|
+
/**
|
|
8
|
+
* Rewrites dependency ranges in every workspace package.json according to upgrade mode.
|
|
9
|
+
*/
|
|
10
|
+
export async function rewriteWorkspace(root, mode) {
|
|
11
|
+
const workspaces = await listWorkspacePackages(root);
|
|
12
|
+
for (const ws of workspaces) {
|
|
13
|
+
const pkg = await readJsonFile(ws.packageJsonPath);
|
|
14
|
+
const next = rewritePackageJson(pkg, mode);
|
|
15
|
+
await writeJsonFile(ws.packageJsonPath, next);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Re-pins every workspace package.json to exact versions from the given lockfile.
|
|
20
|
+
*/
|
|
21
|
+
export async function repinWorkspace(root, lockfilePath, packageManager) {
|
|
22
|
+
const workspaces = await listWorkspacePackages(root);
|
|
23
|
+
for (const ws of workspaces) {
|
|
24
|
+
const locked = await lockedVersionsForImporter({
|
|
25
|
+
lockfilePath,
|
|
26
|
+
packageManager,
|
|
27
|
+
importerDir: ws.relativeDir,
|
|
28
|
+
});
|
|
29
|
+
const pkg = await readJsonFile(ws.packageJsonPath);
|
|
30
|
+
const next = rePinPackageJson(pkg, locked);
|
|
31
|
+
await writeJsonFile(ws.packageJsonPath, next);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Joins a project root with its lockfile basename.
|
|
36
|
+
*/
|
|
37
|
+
export function lockfilePathFor(root, lockfileName) {
|
|
38
|
+
return path.join(root, lockfileName);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/rewrite/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAY,EACZ,IAAiB;IAEjB,MAAM,UAAU,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,YAAY,CAAc,EAAE,CAAC,eAAe,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,aAAa,CAAC,EAAE,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,YAAoB,EACpB,cAA8B;IAE9B,MAAM,UAAU,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC;YAC7C,YAAY;YACZ,cAAc;YACd,WAAW,EAAE,EAAE,CAAC,WAAW;SAC5B,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,YAAY,CAAc,EAAE,CAAC,eAAe,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,aAAa,CAAC,EAAE,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,YAAoB;IAChE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { AdvisoryRef } from "./refs.js";
|
|
2
|
+
/** Closed set of vulnerability severities used in security reports. */
|
|
3
|
+
export declare const FindingSeverities: {
|
|
4
|
+
readonly Critical: "critical";
|
|
5
|
+
readonly High: "high";
|
|
6
|
+
readonly Moderate: "moderate";
|
|
7
|
+
readonly Low: "low";
|
|
8
|
+
readonly Info: "info";
|
|
9
|
+
};
|
|
10
|
+
/** Severity level for a security finding. */
|
|
11
|
+
export type FindingSeverity = (typeof FindingSeverities)[keyof typeof FindingSeverities];
|
|
12
|
+
/** Closed set of scanners that can produce a security finding. */
|
|
13
|
+
export declare const SecuritySources: {
|
|
14
|
+
readonly NpmAudit: "npm-audit";
|
|
15
|
+
readonly CveLite: "cve-lite";
|
|
16
|
+
};
|
|
17
|
+
/** Scanner that produced a security finding. */
|
|
18
|
+
export type SecuritySource = (typeof SecuritySources)[keyof typeof SecuritySources];
|
|
19
|
+
export interface SecurityFinding {
|
|
20
|
+
/** Primary identity for classification (prefer GHSA, then CVE, then OSV). */
|
|
21
|
+
id: string;
|
|
22
|
+
/** Public CVE / GHSA / OSV references for this vulnerability. */
|
|
23
|
+
refs: AdvisoryRef[];
|
|
24
|
+
/**
|
|
25
|
+
* Parent package names when this row is an npm meta-vuln (via strings only).
|
|
26
|
+
* Empty/undefined for findings with real advisory objects.
|
|
27
|
+
*/
|
|
28
|
+
viaPackages?: string[];
|
|
29
|
+
packageName: string;
|
|
30
|
+
version?: string;
|
|
31
|
+
severity: FindingSeverity;
|
|
32
|
+
source: SecuritySource;
|
|
33
|
+
title?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ClassifiedFindings {
|
|
36
|
+
fixed: SecurityFinding[];
|
|
37
|
+
introduced: SecurityFinding[];
|
|
38
|
+
/** Present before and after the upgrade — still open / unfixed. */
|
|
39
|
+
unresolved: SecurityFinding[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Maps a raw severity string from a scanner into a normalized FindingSeverity.
|
|
43
|
+
*/
|
|
44
|
+
export declare function normalizeSeverity(raw: string | undefined): FindingSeverity;
|
|
45
|
+
/**
|
|
46
|
+
* Classifies findings as fixed, introduced, or unresolved by comparing before/after scans.
|
|
47
|
+
*/
|
|
48
|
+
export declare function classifyFindings(before: SecurityFinding[], after: SecurityFinding[]): ClassifiedFindings;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Closed set of vulnerability severities used in security reports. */
|
|
2
|
+
export const FindingSeverities = {
|
|
3
|
+
Critical: "critical",
|
|
4
|
+
High: "high",
|
|
5
|
+
Moderate: "moderate",
|
|
6
|
+
Low: "low",
|
|
7
|
+
Info: "info",
|
|
8
|
+
};
|
|
9
|
+
/** Closed set of scanners that can produce a security finding. */
|
|
10
|
+
export const SecuritySources = {
|
|
11
|
+
NpmAudit: "npm-audit",
|
|
12
|
+
CveLite: "cve-lite",
|
|
13
|
+
};
|
|
14
|
+
const SEVERITY_ORDER = [
|
|
15
|
+
FindingSeverities.Critical,
|
|
16
|
+
FindingSeverities.High,
|
|
17
|
+
FindingSeverities.Moderate,
|
|
18
|
+
FindingSeverities.Low,
|
|
19
|
+
FindingSeverities.Info,
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Maps a raw severity string from a scanner into a normalized FindingSeverity.
|
|
23
|
+
*/
|
|
24
|
+
export function normalizeSeverity(raw) {
|
|
25
|
+
const value = (raw ?? FindingSeverities.Info).toLowerCase();
|
|
26
|
+
if (value === FindingSeverities.Critical) {
|
|
27
|
+
return FindingSeverities.Critical;
|
|
28
|
+
}
|
|
29
|
+
if (value === FindingSeverities.High) {
|
|
30
|
+
return FindingSeverities.High;
|
|
31
|
+
}
|
|
32
|
+
if (value === FindingSeverities.Moderate || value === "medium") {
|
|
33
|
+
return FindingSeverities.Moderate;
|
|
34
|
+
}
|
|
35
|
+
if (value === FindingSeverities.Low) {
|
|
36
|
+
return FindingSeverities.Low;
|
|
37
|
+
}
|
|
38
|
+
return FindingSeverities.Info;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Builds a stable identity key for a finding (id + package name).
|
|
42
|
+
*/
|
|
43
|
+
function findingKey(finding) {
|
|
44
|
+
return `${finding.id}::${finding.packageName}`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sorts findings by severity (highest first), then by identity key.
|
|
48
|
+
*/
|
|
49
|
+
function sortFindings(findings) {
|
|
50
|
+
return [...findings].sort((a, b) => {
|
|
51
|
+
const severity = SEVERITY_ORDER.indexOf(a.severity) - SEVERITY_ORDER.indexOf(b.severity);
|
|
52
|
+
if (severity !== 0) {
|
|
53
|
+
return severity;
|
|
54
|
+
}
|
|
55
|
+
return findingKey(a).localeCompare(findingKey(b));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Classifies findings as fixed, introduced, or unresolved by comparing before/after scans.
|
|
60
|
+
*/
|
|
61
|
+
export function classifyFindings(before, after) {
|
|
62
|
+
const beforeMap = new Map(before.map((item) => [findingKey(item), item]));
|
|
63
|
+
const afterMap = new Map(after.map((item) => [findingKey(item), item]));
|
|
64
|
+
const fixed = [];
|
|
65
|
+
const introduced = [];
|
|
66
|
+
const unresolved = [];
|
|
67
|
+
for (const [key, finding] of beforeMap) {
|
|
68
|
+
if (afterMap.has(key)) {
|
|
69
|
+
unresolved.push(afterMap.get(key) ?? finding);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
fixed.push(finding);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
for (const [key, finding] of afterMap) {
|
|
76
|
+
if (!beforeMap.has(key)) {
|
|
77
|
+
introduced.push(finding);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
fixed: sortFindings(fixed),
|
|
82
|
+
introduced: sortFindings(introduced),
|
|
83
|
+
unresolved: sortFindings(unresolved),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/security/classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type SecurityFinding } from "./classify.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parses cve-lite JSON output into normalized SecurityFinding entries.
|
|
4
|
+
* Collects CVE / GHSA / OSV refs from common field names and aliases.
|
|
5
|
+
* Returns an empty list when the payload is not valid JSON.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseCveLiteJson(raw: string): SecurityFinding[];
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { normalizeSeverity, SecuritySources, } from "./classify.js";
|
|
2
|
+
import { primaryFindingId, refsFromScannerFields } from "./refs.js";
|
|
3
|
+
/**
|
|
4
|
+
* Narrows an unknown value to a plain object record, or undefined.
|
|
5
|
+
*/
|
|
6
|
+
function asRecord(value) {
|
|
7
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Extracts a findings array from cve-lite JSON (top-level array or known keys).
|
|
14
|
+
*/
|
|
15
|
+
function collectArray(value) {
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
const rec = asRecord(value);
|
|
20
|
+
if (!rec) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
for (const key of ["findings", "vulnerabilities", "issues", "results"]) {
|
|
24
|
+
if (Array.isArray(rec[key])) {
|
|
25
|
+
return rec[key];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Parses cve-lite JSON output into normalized SecurityFinding entries.
|
|
32
|
+
* Collects CVE / GHSA / OSV refs from common field names and aliases.
|
|
33
|
+
* Returns an empty list when the payload is not valid JSON.
|
|
34
|
+
*/
|
|
35
|
+
export function parseCveLiteJson(raw) {
|
|
36
|
+
let parsed;
|
|
37
|
+
try {
|
|
38
|
+
parsed = JSON.parse(raw);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
const items = collectArray(parsed);
|
|
44
|
+
const findings = [];
|
|
45
|
+
for (const item of items) {
|
|
46
|
+
const rec = asRecord(item);
|
|
47
|
+
if (!rec) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const packageName = (typeof rec.package === "string" && rec.package) ||
|
|
51
|
+
(typeof rec.packageName === "string" && rec.packageName) ||
|
|
52
|
+
(typeof rec.name === "string" && rec.name) ||
|
|
53
|
+
undefined;
|
|
54
|
+
if (!packageName) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const refs = refsFromScannerFields({
|
|
58
|
+
id: rec.id,
|
|
59
|
+
cve: rec.cve,
|
|
60
|
+
ghsa: rec.ghsa,
|
|
61
|
+
osvId: rec.osvId,
|
|
62
|
+
aliases: rec.aliases,
|
|
63
|
+
url: rec.url,
|
|
64
|
+
});
|
|
65
|
+
const fallback = `${packageName}:${String(rec.version ?? "")}`;
|
|
66
|
+
findings.push({
|
|
67
|
+
id: primaryFindingId(refs, fallback),
|
|
68
|
+
refs,
|
|
69
|
+
packageName,
|
|
70
|
+
version: typeof rec.version === "string" ? rec.version : undefined,
|
|
71
|
+
severity: normalizeSeverity(typeof rec.severity === "string" ? rec.severity : undefined),
|
|
72
|
+
source: SecuritySources.CveLite,
|
|
73
|
+
title: typeof rec.title === "string" ? rec.title : undefined,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return findings;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=cve-lite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cve-lite.js","sourceRoot":"","sources":["../../src/security/cve-lite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type SecurityFinding } from "./classify.js";
|
|
2
|
+
/** Title used for npm meta-vulns that only depend on other vulnerable packages. */
|
|
3
|
+
export declare const META_VULN_TITLE = "Depends on vulnerable package(s)";
|
|
4
|
+
/**
|
|
5
|
+
* Parses `npm audit --json` output into normalized SecurityFinding entries.
|
|
6
|
+
* Prefers GHSA/CVE refs extracted from advisory URLs over numeric npm advisory ids.
|
|
7
|
+
* Meta-vulns (via package-name strings only) are kept with viaPackages labels.
|
|
8
|
+
* Returns an empty list when the payload is not valid JSON.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseNpmAuditJson(raw: string): SecurityFinding[];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { normalizeSeverity, SecuritySources, } from "./classify.js";
|
|
2
|
+
import { primaryFindingId, dedupeRefs, refsFromText } from "./refs.js";
|
|
3
|
+
/** Title used for npm meta-vulns that only depend on other vulnerable packages. */
|
|
4
|
+
export const META_VULN_TITLE = "Depends on vulnerable package(s)";
|
|
5
|
+
/**
|
|
6
|
+
* Parses `npm audit --json` output into normalized SecurityFinding entries.
|
|
7
|
+
* Prefers GHSA/CVE refs extracted from advisory URLs over numeric npm advisory ids.
|
|
8
|
+
* Meta-vulns (via package-name strings only) are kept with viaPackages labels.
|
|
9
|
+
* Returns an empty list when the payload is not valid JSON.
|
|
10
|
+
*/
|
|
11
|
+
export function parseNpmAuditJson(raw) {
|
|
12
|
+
let parsed;
|
|
13
|
+
try {
|
|
14
|
+
parsed = JSON.parse(raw);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const findings = [];
|
|
20
|
+
for (const [packageName, vuln] of Object.entries(parsed.vulnerabilities ?? {})) {
|
|
21
|
+
const vias = Array.isArray(vuln.via) ? vuln.via : [];
|
|
22
|
+
const advisoryVias = vias.filter((item) => typeof item === "object" && item !== null);
|
|
23
|
+
const viaPackages = vias
|
|
24
|
+
.filter((item) => typeof item === "string")
|
|
25
|
+
.map((item) => item.trim())
|
|
26
|
+
.filter((item) => item.length > 0)
|
|
27
|
+
.sort((a, b) => a.localeCompare(b));
|
|
28
|
+
if (advisoryVias.length === 0) {
|
|
29
|
+
const fallback = `npm:${packageName}`;
|
|
30
|
+
findings.push({
|
|
31
|
+
id: fallback,
|
|
32
|
+
refs: [],
|
|
33
|
+
viaPackages: viaPackages.length > 0 ? viaPackages : undefined,
|
|
34
|
+
packageName: vuln.name ?? packageName,
|
|
35
|
+
severity: normalizeSeverity(vuln.severity),
|
|
36
|
+
source: SecuritySources.NpmAudit,
|
|
37
|
+
title: META_VULN_TITLE,
|
|
38
|
+
});
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
for (const via of advisoryVias) {
|
|
42
|
+
const refs = dedupeRefs([
|
|
43
|
+
...refsFromText(via.url),
|
|
44
|
+
...refsFromText(typeof via.cve === "string" ? via.cve : undefined),
|
|
45
|
+
...(Array.isArray(via.cve)
|
|
46
|
+
? via.cve.flatMap((item) => refsFromText(item))
|
|
47
|
+
: []),
|
|
48
|
+
...refsFromText(via.title),
|
|
49
|
+
]);
|
|
50
|
+
const fallback = via.source !== undefined
|
|
51
|
+
? `npm:${via.source}`
|
|
52
|
+
: via.url ?? via.title ?? packageName;
|
|
53
|
+
findings.push({
|
|
54
|
+
id: primaryFindingId(refs, fallback),
|
|
55
|
+
refs,
|
|
56
|
+
packageName: via.name ?? vuln.name ?? packageName,
|
|
57
|
+
severity: normalizeSeverity(via.severity ?? vuln.severity),
|
|
58
|
+
source: SecuritySources.NpmAudit,
|
|
59
|
+
title: via.title,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return findings;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=npm-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-audit.js","sourceRoot":"","sources":["../../src/security/npm-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Closed set of public vulnerability reference kinds. */
|
|
2
|
+
export declare const AdvisoryRefKinds: {
|
|
3
|
+
readonly Cve: "cve";
|
|
4
|
+
readonly Ghsa: "ghsa";
|
|
5
|
+
readonly Osv: "osv";
|
|
6
|
+
};
|
|
7
|
+
/** Kind of public advisory identifier (CVE, GHSA, or OSV). */
|
|
8
|
+
export type AdvisoryRefKind = (typeof AdvisoryRefKinds)[keyof typeof AdvisoryRefKinds];
|
|
9
|
+
/** A lookup-able vulnerability reference with a stable public URL. */
|
|
10
|
+
export interface AdvisoryRef {
|
|
11
|
+
id: string;
|
|
12
|
+
kind: AdvisoryRefKind;
|
|
13
|
+
url: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Builds the canonical GitHub Advisory Database URL for a GHSA id.
|
|
17
|
+
*/
|
|
18
|
+
export declare function urlForGhsa(id: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Builds the NVD detail URL for a CVE id.
|
|
21
|
+
*/
|
|
22
|
+
export declare function urlForCve(id: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Builds the OSV.dev vulnerability URL for an OSV id.
|
|
25
|
+
* Path-encodes the id so punctuation cannot break markdown links.
|
|
26
|
+
*/
|
|
27
|
+
export declare function urlForOsv(id: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Creates an AdvisoryRef for a known id string, or undefined when unrecognized.
|
|
30
|
+
* Only validated id shapes become refs (avoids markdown / URL injection via ids).
|
|
31
|
+
*/
|
|
32
|
+
export declare function refFromId(raw: string): AdvisoryRef | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Extracts GHSA/CVE/OSV ids mentioned in free text or a URL.
|
|
35
|
+
*/
|
|
36
|
+
export declare function refsFromText(text: string | undefined): AdvisoryRef[];
|
|
37
|
+
/**
|
|
38
|
+
* Collects refs from common scanner field shapes (string, string[], or nested).
|
|
39
|
+
*/
|
|
40
|
+
export declare function refsFromScannerFields(fields: {
|
|
41
|
+
id?: unknown;
|
|
42
|
+
cve?: unknown;
|
|
43
|
+
ghsa?: unknown;
|
|
44
|
+
osvId?: unknown;
|
|
45
|
+
aliases?: unknown;
|
|
46
|
+
url?: unknown;
|
|
47
|
+
}): AdvisoryRef[];
|
|
48
|
+
/**
|
|
49
|
+
* Dedupes refs by id, preserving first-seen order (GHSA/CVE/OSV as discovered).
|
|
50
|
+
*/
|
|
51
|
+
export declare function dedupeRefs(refs: AdvisoryRef[]): AdvisoryRef[];
|
|
52
|
+
/**
|
|
53
|
+
* Picks a stable primary finding id from refs, or a provided fallback.
|
|
54
|
+
*/
|
|
55
|
+
export declare function primaryFindingId(refs: AdvisoryRef[], fallback: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Renders refs as markdown hyperlinks, comma-separated.
|
|
58
|
+
*/
|
|
59
|
+
export declare function formatRefsMarkdown(refs: AdvisoryRef[]): string;
|
|
60
|
+
/**
|
|
61
|
+
* Renders refs as plain text ids, comma-separated (URLs omitted for terminal density).
|
|
62
|
+
*/
|
|
63
|
+
export declare function formatRefsText(refs: AdvisoryRef[]): string;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/** Closed set of public vulnerability reference kinds. */
|
|
2
|
+
export const AdvisoryRefKinds = {
|
|
3
|
+
Cve: "cve",
|
|
4
|
+
Ghsa: "ghsa",
|
|
5
|
+
Osv: "osv",
|
|
6
|
+
};
|
|
7
|
+
const GHSA_RE = /\bGHSA-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}\b/i;
|
|
8
|
+
const CVE_RE = /\bCVE-\d{4}-\d+\b/i;
|
|
9
|
+
/** OSV ids mentioned inside free text (word-bounded). */
|
|
10
|
+
const OSV_RE = /\bOSV-[A-Za-z0-9._-]+\b/;
|
|
11
|
+
/** Full-string OSV id used for refs / URL path segments. */
|
|
12
|
+
const OSV_ID_RE = /^OSV-[A-Za-z0-9._-]+$/;
|
|
13
|
+
/**
|
|
14
|
+
* Encodes a single URL path segment so attacker-controlled ids cannot break
|
|
15
|
+
* out of the path or inject markdown / HTML into report links.
|
|
16
|
+
* Extends encodeURIComponent to also percent-encode `()` (not encoded by default,
|
|
17
|
+
* but they break markdown `[text](url)` links).
|
|
18
|
+
*/
|
|
19
|
+
function encodePathSegment(segment) {
|
|
20
|
+
return encodeURIComponent(segment)
|
|
21
|
+
.replace(/\(/g, "%28")
|
|
22
|
+
.replace(/\)/g, "%29");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Builds the canonical GitHub Advisory Database URL for a GHSA id.
|
|
26
|
+
*/
|
|
27
|
+
export function urlForGhsa(id) {
|
|
28
|
+
return `https://github.com/advisories/${encodePathSegment(normalizeGhsa(id))}`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Builds the NVD detail URL for a CVE id.
|
|
32
|
+
*/
|
|
33
|
+
export function urlForCve(id) {
|
|
34
|
+
return `https://nvd.nist.gov/vuln/detail/${encodePathSegment(normalizeCve(id))}`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Builds the OSV.dev vulnerability URL for an OSV id.
|
|
38
|
+
* Path-encodes the id so punctuation cannot break markdown links.
|
|
39
|
+
*/
|
|
40
|
+
export function urlForOsv(id) {
|
|
41
|
+
return `https://osv.dev/vulnerability/${encodePathSegment(id)}`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Normalizes a GHSA id to GHSA-… with lowercase suffix (GitHub canonical form).
|
|
45
|
+
* Returns the original string when it does not contain a GHSA match.
|
|
46
|
+
*/
|
|
47
|
+
function normalizeGhsa(id) {
|
|
48
|
+
const match = id.match(GHSA_RE);
|
|
49
|
+
if (!match) {
|
|
50
|
+
return id;
|
|
51
|
+
}
|
|
52
|
+
return `GHSA-${match[0].slice(5).toLowerCase()}`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Normalizes a CVE id to CVE-YYYY-NNNN uppercase form.
|
|
56
|
+
* Returns the original string when it does not contain a CVE match.
|
|
57
|
+
*/
|
|
58
|
+
function normalizeCve(id) {
|
|
59
|
+
const match = id.match(CVE_RE);
|
|
60
|
+
if (!match) {
|
|
61
|
+
return id;
|
|
62
|
+
}
|
|
63
|
+
return match[0].toUpperCase();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* True when the whole string is a canonical GHSA id.
|
|
67
|
+
*/
|
|
68
|
+
function isGhsaId(value) {
|
|
69
|
+
return /^GHSA-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}$/i.test(value);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* True when the whole string is a canonical CVE id.
|
|
73
|
+
*/
|
|
74
|
+
function isCveId(value) {
|
|
75
|
+
return /^CVE-\d{4}-\d+$/i.test(value);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Creates an AdvisoryRef for a known id string, or undefined when unrecognized.
|
|
79
|
+
* Only validated id shapes become refs (avoids markdown / URL injection via ids).
|
|
80
|
+
*/
|
|
81
|
+
export function refFromId(raw) {
|
|
82
|
+
const value = raw.trim();
|
|
83
|
+
if (!value) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
if (isGhsaId(value)) {
|
|
87
|
+
const id = normalizeGhsa(value);
|
|
88
|
+
return { id, kind: AdvisoryRefKinds.Ghsa, url: urlForGhsa(id) };
|
|
89
|
+
}
|
|
90
|
+
if (isCveId(value)) {
|
|
91
|
+
const id = normalizeCve(value);
|
|
92
|
+
return { id, kind: AdvisoryRefKinds.Cve, url: urlForCve(id) };
|
|
93
|
+
}
|
|
94
|
+
if (OSV_ID_RE.test(value)) {
|
|
95
|
+
return { id: value, kind: AdvisoryRefKinds.Osv, url: urlForOsv(value) };
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extracts GHSA/CVE/OSV ids mentioned in free text or a URL.
|
|
101
|
+
*/
|
|
102
|
+
export function refsFromText(text) {
|
|
103
|
+
if (!text) {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
const found = [];
|
|
107
|
+
for (const match of text.matchAll(new RegExp(GHSA_RE, "gi"))) {
|
|
108
|
+
const ref = refFromId(match[0]);
|
|
109
|
+
if (ref) {
|
|
110
|
+
found.push(ref);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
for (const match of text.matchAll(new RegExp(CVE_RE, "gi"))) {
|
|
114
|
+
const ref = refFromId(match[0]);
|
|
115
|
+
if (ref) {
|
|
116
|
+
found.push(ref);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const match of text.matchAll(new RegExp(OSV_RE, "g"))) {
|
|
120
|
+
const ref = refFromId(match[0]);
|
|
121
|
+
if (ref) {
|
|
122
|
+
found.push(ref);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return dedupeRefs(found);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Collects refs from common scanner field shapes (string, string[], or nested).
|
|
129
|
+
*/
|
|
130
|
+
export function refsFromScannerFields(fields) {
|
|
131
|
+
const collected = [];
|
|
132
|
+
for (const value of [
|
|
133
|
+
fields.id,
|
|
134
|
+
fields.cve,
|
|
135
|
+
fields.ghsa,
|
|
136
|
+
fields.osvId,
|
|
137
|
+
fields.aliases,
|
|
138
|
+
fields.url,
|
|
139
|
+
]) {
|
|
140
|
+
for (const item of asStringList(value)) {
|
|
141
|
+
const direct = refFromId(item);
|
|
142
|
+
if (direct) {
|
|
143
|
+
collected.push(direct);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
collected.push(...refsFromText(item));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return dedupeRefs(collected);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Dedupes refs by id, preserving first-seen order (GHSA/CVE/OSV as discovered).
|
|
154
|
+
*/
|
|
155
|
+
export function dedupeRefs(refs) {
|
|
156
|
+
const seen = new Set();
|
|
157
|
+
const out = [];
|
|
158
|
+
for (const ref of refs) {
|
|
159
|
+
const key = ref.id.toUpperCase();
|
|
160
|
+
if (seen.has(key)) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
seen.add(key);
|
|
164
|
+
out.push(ref);
|
|
165
|
+
}
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Picks a stable primary finding id from refs, or a provided fallback.
|
|
170
|
+
*/
|
|
171
|
+
export function primaryFindingId(refs, fallback) {
|
|
172
|
+
if (refs.length === 0) {
|
|
173
|
+
return fallback;
|
|
174
|
+
}
|
|
175
|
+
const ghsa = refs.find((ref) => ref.kind === AdvisoryRefKinds.Ghsa);
|
|
176
|
+
if (ghsa) {
|
|
177
|
+
return ghsa.id;
|
|
178
|
+
}
|
|
179
|
+
const cve = refs.find((ref) => ref.kind === AdvisoryRefKinds.Cve);
|
|
180
|
+
if (cve) {
|
|
181
|
+
return cve.id;
|
|
182
|
+
}
|
|
183
|
+
return refs[0]?.id ?? fallback;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Renders refs as markdown hyperlinks, comma-separated.
|
|
187
|
+
*/
|
|
188
|
+
export function formatRefsMarkdown(refs) {
|
|
189
|
+
if (refs.length === 0) {
|
|
190
|
+
return "—";
|
|
191
|
+
}
|
|
192
|
+
return refs.map((ref) => `[${ref.id}](${ref.url})`).join(", ");
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Renders refs as plain text ids, comma-separated (URLs omitted for terminal density).
|
|
196
|
+
*/
|
|
197
|
+
export function formatRefsText(refs) {
|
|
198
|
+
if (refs.length === 0) {
|
|
199
|
+
return "—";
|
|
200
|
+
}
|
|
201
|
+
return refs.map((ref) => ref.id).join(", ");
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Flattens unknown scanner values into a list of strings.
|
|
205
|
+
*/
|
|
206
|
+
function asStringList(value) {
|
|
207
|
+
if (typeof value === "string") {
|
|
208
|
+
return [value];
|
|
209
|
+
}
|
|
210
|
+
if (typeof value === "number") {
|
|
211
|
+
return [String(value)];
|
|
212
|
+
}
|
|
213
|
+
if (Array.isArray(value)) {
|
|
214
|
+
return value.flatMap((item) => asStringList(item));
|
|
215
|
+
}
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refs.js","sourceRoot":"","sources":["../../src/security/refs.ts"],"names":[],"mappings":"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"}
|