audit-trace 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -0
- package/dist/cli/ink/ReportTui.d.ts +8 -0
- package/dist/cli/ink/ReportTui.d.ts.map +1 -0
- package/dist/cli/ink/ReportTui.js +20 -0
- package/dist/cli/ink/ReportTui.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +150 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/audit-parser/normalize.d.ts +8 -0
- package/dist/core/audit-parser/normalize.d.ts.map +1 -0
- package/dist/core/audit-parser/normalize.js +107 -0
- package/dist/core/audit-parser/normalize.js.map +1 -0
- package/dist/core/audit-parser/run-audit.d.ts +9 -0
- package/dist/core/audit-parser/run-audit.d.ts.map +1 -0
- package/dist/core/audit-parser/run-audit.js +25 -0
- package/dist/core/audit-parser/run-audit.js.map +1 -0
- package/dist/core/graph-engine/load-lockfile.d.ts +20 -0
- package/dist/core/graph-engine/load-lockfile.d.ts.map +1 -0
- package/dist/core/graph-engine/load-lockfile.js +43 -0
- package/dist/core/graph-engine/load-lockfile.js.map +1 -0
- package/dist/core/graph-engine/npm-lock.d.ts +5 -0
- package/dist/core/graph-engine/npm-lock.d.ts.map +1 -0
- package/dist/core/graph-engine/npm-lock.js +159 -0
- package/dist/core/graph-engine/npm-lock.js.map +1 -0
- package/dist/core/graph-engine/pnpm-lock.d.ts +4 -0
- package/dist/core/graph-engine/pnpm-lock.d.ts.map +1 -0
- package/dist/core/graph-engine/pnpm-lock.js +152 -0
- package/dist/core/graph-engine/pnpm-lock.js.map +1 -0
- package/dist/core/graph-engine/traverse.d.ts +17 -0
- package/dist/core/graph-engine/traverse.d.ts.map +1 -0
- package/dist/core/graph-engine/traverse.js +125 -0
- package/dist/core/graph-engine/traverse.js.map +1 -0
- package/dist/core/graph-engine/yarn-lock.d.ts +4 -0
- package/dist/core/graph-engine/yarn-lock.d.ts.map +1 -0
- package/dist/core/graph-engine/yarn-lock.js +128 -0
- package/dist/core/graph-engine/yarn-lock.js.map +1 -0
- package/dist/core/models.d.ts +88 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +9 -0
- package/dist/core/models.js.map +1 -0
- package/dist/core/ownership/tracer.d.ts +16 -0
- package/dist/core/ownership/tracer.d.ts.map +1 -0
- package/dist/core/ownership/tracer.js +65 -0
- package/dist/core/ownership/tracer.js.map +1 -0
- package/dist/core/remediation-engine/engine.d.ts +3 -0
- package/dist/core/remediation-engine/engine.d.ts.map +1 -0
- package/dist/core/remediation-engine/engine.js +42 -0
- package/dist/core/remediation-engine/engine.js.map +1 -0
- package/dist/core/risk-engine/scripts.d.ts +6 -0
- package/dist/core/risk-engine/scripts.d.ts.map +1 -0
- package/dist/core/risk-engine/scripts.js +19 -0
- package/dist/core/risk-engine/scripts.js.map +1 -0
- package/dist/core/risk-engine/workspace-risk.d.ts +2 -0
- package/dist/core/risk-engine/workspace-risk.d.ts.map +1 -0
- package/dist/core/risk-engine/workspace-risk.js +2 -0
- package/dist/core/risk-engine/workspace-risk.js.map +1 -0
- package/dist/core/workspace-engine/detect.d.ts +3 -0
- package/dist/core/workspace-engine/detect.d.ts.map +1 -0
- package/dist/core/workspace-engine/detect.js +53 -0
- package/dist/core/workspace-engine/detect.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/ink/ReportTui.d.ts +8 -0
- package/dist/ink/ReportTui.d.ts.map +1 -0
- package/dist/ink/ReportTui.js +20 -0
- package/dist/ink/ReportTui.js.map +1 -0
- package/dist/integrations/ci-mode/policy.d.ts +17 -0
- package/dist/integrations/ci-mode/policy.d.ts.map +1 -0
- package/dist/integrations/ci-mode/policy.js +71 -0
- package/dist/integrations/ci-mode/policy.js.map +1 -0
- package/dist/integrations/lockfile-diff/compare.d.ts +11 -0
- package/dist/integrations/lockfile-diff/compare.d.ts.map +1 -0
- package/dist/integrations/lockfile-diff/compare.js +44 -0
- package/dist/integrations/lockfile-diff/compare.js.map +1 -0
- package/dist/integrations/reachability/madge-check.d.ts +12 -0
- package/dist/integrations/reachability/madge-check.d.ts.map +1 -0
- package/dist/integrations/reachability/madge-check.js +41 -0
- package/dist/integrations/reachability/madge-check.js.map +1 -0
- package/dist/lib/analyze.d.ts +22 -0
- package/dist/lib/analyze.d.ts.map +1 -0
- package/dist/lib/analyze.js +107 -0
- package/dist/lib/analyze.js.map +1 -0
- package/dist/output/html-reporter.d.ts +4 -0
- package/dist/output/html-reporter.d.ts.map +1 -0
- package/dist/output/html-reporter.js +18 -0
- package/dist/output/html-reporter.js.map +1 -0
- package/dist/output/json-reporter.d.ts +5 -0
- package/dist/output/json-reporter.d.ts.map +1 -0
- package/dist/output/json-reporter.js +18 -0
- package/dist/output/json-reporter.js.map +1 -0
- package/dist/output/markdown-reporter.d.ts +4 -0
- package/dist/output/markdown-reporter.d.ts.map +1 -0
- package/dist/output/markdown-reporter.js +28 -0
- package/dist/output/markdown-reporter.js.map +1 -0
- package/dist/output/terminal-renderer.d.ts +8 -0
- package/dist/output/terminal-renderer.d.ts.map +1 -0
- package/dist/output/terminal-renderer.js +51 -0
- package/dist/output/terminal-renderer.js.map +1 -0
- package/dist/output/tree-format.d.ts +3 -0
- package/dist/output/tree-format.d.ts.map +1 -0
- package/dist/output/tree-format.js +12 -0
- package/dist/output/tree-format.js.map +1 -0
- package/dist/plugins/registry.d.ts +4 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +8 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/types.d.ts +10 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +2 -0
- package/dist/plugins/types.js.map +1 -0
- package/examples/github-actions/ci.yml +34 -0
- package/package.json +58 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import madge from "madge";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Best-effort: if madge dependency graph includes the package name under node_modules, treat as reachable.
|
|
5
|
+
*/
|
|
6
|
+
export async function checkRuntimeReachable(entryFile, packageName, cwd) {
|
|
7
|
+
const abs = resolve(cwd, entryFile);
|
|
8
|
+
try {
|
|
9
|
+
const tree = await madge(abs, {
|
|
10
|
+
baseDir: cwd,
|
|
11
|
+
includeNpm: true,
|
|
12
|
+
fileExtensions: ["ts", "tsx", "js", "jsx", "mjs", "cjs"],
|
|
13
|
+
});
|
|
14
|
+
const obj = tree.obj();
|
|
15
|
+
const needle = `node_modules/${packageName}/`;
|
|
16
|
+
const needleScoped = packageName.startsWith("@")
|
|
17
|
+
? `node_modules/${packageName.replace("/", "/")}/`
|
|
18
|
+
: needle;
|
|
19
|
+
for (const [k, deps] of Object.entries(obj)) {
|
|
20
|
+
if (k.includes(needle) || k.includes(needleScoped)) {
|
|
21
|
+
return { status: "reachable", evidence: `Graph includes ${k}` };
|
|
22
|
+
}
|
|
23
|
+
for (const d of deps) {
|
|
24
|
+
if (d.includes(needle) || d.includes(needleScoped)) {
|
|
25
|
+
return { status: "reachable", evidence: `Import path via ${d}` };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
status: "not_reachable",
|
|
31
|
+
evidence: "No module path in madge graph referenced this package (heuristic; may be dynamic require).",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
return {
|
|
36
|
+
status: "unknown",
|
|
37
|
+
evidence: e instanceof Error ? e.message : String(e),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=madge-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"madge-check.js","sourceRoot":"","sources":["../../../src/integrations/reachability/madge-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,SAAiB,EACjB,WAAmB,EACnB,GAAW;IAEX,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC5B,OAAO,EAAE,GAAG;YACZ,UAAU,EAAE,IAAI;YAChB,cAAc,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;SACzD,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAA8B,CAAC;QACnD,MAAM,MAAM,GAAG,gBAAgB,WAAW,GAAG,CAAC;QAC9C,MAAM,YAAY,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC;YAC9C,CAAC,CAAC,gBAAgB,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG;YAClD,CAAC,CAAC,MAAM,CAAC;QACX,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACnD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EAAE,EAAE,CAAC;YAClE,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;oBACnD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,mBAAmB,CAAC,EAAE,EAAE,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO;YACL,MAAM,EAAE,eAAe;YACvB,QAAQ,EAAE,4FAA4F;SACvG,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;SACrD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AuditReport } from "../core/models.js";
|
|
2
|
+
import { type OwnershipPath } from "../core/ownership/tracer.js";
|
|
3
|
+
import { detectWorkspaces } from "../core/workspace-engine/detect.js";
|
|
4
|
+
import { type CiPolicy } from "../integrations/ci-mode/policy.js";
|
|
5
|
+
export interface AnalyzeOptions {
|
|
6
|
+
cwd: string;
|
|
7
|
+
useAuditFile?: string;
|
|
8
|
+
pm?: "npm" | "pnpm" | "yarn";
|
|
9
|
+
prodOnly?: boolean;
|
|
10
|
+
ci?: boolean;
|
|
11
|
+
ciVerbose?: boolean;
|
|
12
|
+
failOn?: CiPolicy["failOn"];
|
|
13
|
+
runtimeEntry?: string;
|
|
14
|
+
assumeReachable?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function analyze(opts: AnalyzeOptions): Promise<{
|
|
17
|
+
report: AuditReport;
|
|
18
|
+
ownership: OwnershipPath[];
|
|
19
|
+
exitCode: number;
|
|
20
|
+
workspace: Awaited<ReturnType<typeof detectWorkspaces>>;
|
|
21
|
+
}>;
|
|
22
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/lib/analyze.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAwB,MAAM,mBAAmB,CAAC;AAQ3E,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAIhF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAgBD,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;IAC3D,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC;CACzD,CAAC,CAuFD"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { loadLockfileGraph } from "../core/graph-engine/load-lockfile.js";
|
|
4
|
+
import { parseNpmAuditJson, parsePnpmAuditJson, parseYarnAuditJsonLines, } from "../core/audit-parser/normalize.js";
|
|
5
|
+
import { runNpmAudit, runPnpmAudit, runYarnAudit } from "../core/audit-parser/run-audit.js";
|
|
6
|
+
import { traceOwnership } from "../core/ownership/tracer.js";
|
|
7
|
+
import { suggestRemediation } from "../core/remediation-engine/engine.js";
|
|
8
|
+
import { detectWorkspaces } from "../core/workspace-engine/detect.js";
|
|
9
|
+
import { evaluateExit } from "../integrations/ci-mode/policy.js";
|
|
10
|
+
import { getPlugins } from "../plugins/registry.js";
|
|
11
|
+
import { checkRuntimeReachable } from "../integrations/reachability/madge-check.js";
|
|
12
|
+
function parseAuditText(text, defaultPm) {
|
|
13
|
+
const t = text.trim();
|
|
14
|
+
if (t.includes('"type":"auditAdvisory"') || t.includes('"type": "auditAdvisory"')) {
|
|
15
|
+
return parseYarnAuditJsonLines(text);
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const j = JSON.parse(text);
|
|
19
|
+
if (defaultPm === "pnpm")
|
|
20
|
+
return parsePnpmAuditJson(j);
|
|
21
|
+
return parseNpmAuditJson(j);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return parseYarnAuditJsonLines(text);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function analyze(opts) {
|
|
28
|
+
const cwd = resolve(opts.cwd);
|
|
29
|
+
const workspace = await detectWorkspaces(cwd);
|
|
30
|
+
const { graph, lock } = await loadLockfileGraph(cwd);
|
|
31
|
+
for (const p of getPlugins())
|
|
32
|
+
p.afterGraphBuilt?.(graph);
|
|
33
|
+
let auditText = "";
|
|
34
|
+
let auditFallback = false;
|
|
35
|
+
const defaultPm = opts.pm ?? (lock.kind === "pnpm" ? "pnpm" : lock.kind === "yarn" ? "yarn" : "npm");
|
|
36
|
+
if (opts.useAuditFile) {
|
|
37
|
+
auditText = await readFile(resolve(cwd, opts.useAuditFile), "utf8");
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
try {
|
|
41
|
+
if (defaultPm === "pnpm")
|
|
42
|
+
auditText = await runPnpmAudit(cwd);
|
|
43
|
+
else if (defaultPm === "yarn")
|
|
44
|
+
auditText = await runYarnAudit(cwd);
|
|
45
|
+
else
|
|
46
|
+
auditText = await runNpmAudit(cwd);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
auditText = "{}";
|
|
50
|
+
auditFallback = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
let findings = parseAuditText(auditText, defaultPm);
|
|
54
|
+
for (const p of getPlugins())
|
|
55
|
+
p.afterAuditNormalized?.(findings);
|
|
56
|
+
let ownership = graph.nodes.size ? traceOwnership(graph, findings) : [];
|
|
57
|
+
let filteredCount = 0;
|
|
58
|
+
if (opts.prodOnly) {
|
|
59
|
+
const before = findings.length;
|
|
60
|
+
const devPkgs = new Set(ownership.filter((o) => o.isDevDependency).map((o) => o.packageName));
|
|
61
|
+
findings = findings.filter((f) => !devPkgs.has(f.packageName));
|
|
62
|
+
ownership = ownership.filter((o) => !o.isDevDependency);
|
|
63
|
+
filteredCount = before - findings.length;
|
|
64
|
+
}
|
|
65
|
+
if (opts.runtimeEntry && graph.nodes.size) {
|
|
66
|
+
for (const f of findings) {
|
|
67
|
+
const rr = await checkRuntimeReachable(opts.runtimeEntry, f.packageName, cwd);
|
|
68
|
+
f.title = `${f.title ?? ""} [reachability:${rr.status}]`.trim();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const remediation = suggestRemediation(findings);
|
|
72
|
+
const policy = {
|
|
73
|
+
failOn: opts.failOn ?? "high",
|
|
74
|
+
prodOnly: Boolean(opts.prodOnly),
|
|
75
|
+
runtimeReachableOnly: Boolean(opts.runtimeEntry && !opts.assumeReachable),
|
|
76
|
+
};
|
|
77
|
+
const ciResult = evaluateExit(findings, policy, {
|
|
78
|
+
noLockfile: lock.kind === "none",
|
|
79
|
+
auditFallback,
|
|
80
|
+
filteredCount,
|
|
81
|
+
});
|
|
82
|
+
let diagnostics = ciResult.diagnostics;
|
|
83
|
+
const exitCode = opts.ci ? ciResult.exitCode : 0;
|
|
84
|
+
for (const p of getPlugins()) {
|
|
85
|
+
const d = p.onCiDiagnostics?.(diagnostics);
|
|
86
|
+
if (d)
|
|
87
|
+
diagnostics = d;
|
|
88
|
+
}
|
|
89
|
+
const report = {
|
|
90
|
+
findings,
|
|
91
|
+
graph,
|
|
92
|
+
diagnostics,
|
|
93
|
+
remediation,
|
|
94
|
+
};
|
|
95
|
+
for (const p of getPlugins()) {
|
|
96
|
+
const r = p.formatReport?.(report, ownership);
|
|
97
|
+
if (r)
|
|
98
|
+
Object.assign(report, r);
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
report,
|
|
102
|
+
ownership,
|
|
103
|
+
exitCode,
|
|
104
|
+
workspace,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/lib/analyze.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-reporter.d.ts","sourceRoot":"","sources":["../../src/output/html-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,CAuBpF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function toHtmlReport(report, ownership) {
|
|
2
|
+
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3
|
+
const rows = report.findings
|
|
4
|
+
.map((f) => `<tr><td>${esc(f.severity)}</td><td>${esc(f.packageName)}</td><td>${esc(f.title ?? f.id)}</td></tr>`)
|
|
5
|
+
.join("\n");
|
|
6
|
+
const own = ownership
|
|
7
|
+
.slice(0, 100)
|
|
8
|
+
.map((o) => `<li>${esc(o.packageName)} (${esc(o.severity)}) — via ${esc(o.topLevelNames.join(", "))} — dev: ${o.isDevDependency}</li>`)
|
|
9
|
+
.join("\n");
|
|
10
|
+
return `<!DOCTYPE html><html><head><meta charset="utf-8"/><title>audit-trace</title></head><body>
|
|
11
|
+
<h1>audit-trace report</h1>
|
|
12
|
+
<h2>Findings</h2>
|
|
13
|
+
<table border="1" cellpadding="4"><thead><tr><th>Severity</th><th>Package</th><th>Title</th></tr></thead><tbody>${rows}</tbody></table>
|
|
14
|
+
<h2>Ownership</h2><ul>${own}</ul>
|
|
15
|
+
<h2>Diagnostics</h2><pre>${esc(JSON.stringify(report.diagnostics, null, 2))}</pre>
|
|
16
|
+
</body></html>`;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=html-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-reporter.js","sourceRoot":"","sources":["../../src/output/html-reporter.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,YAAY,CAAC,MAAmB,EAAE,SAA0B;IAC1E,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CACxB,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ;SACzB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,WAAW,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,YAAY,CACvG;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,GAAG,GAAG,SAAS;SAClB,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;SACb,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,CAAC,eAAe,OAAO,CAC7H;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO;;;kHAGyG,IAAI;wBAC9F,GAAG;2BACA,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;eAC5D,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-reporter.d.ts","sourceRoot":"","sources":["../../src/output/json-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,MAAM,CAgBhG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function toJsonReport(report) {
|
|
2
|
+
const serializable = {
|
|
3
|
+
...report,
|
|
4
|
+
graph: report.graph
|
|
5
|
+
? {
|
|
6
|
+
lockfileKind: report.graph.lockfileKind,
|
|
7
|
+
nodeCount: report.graph.nodes.size,
|
|
8
|
+
edgeCount: report.graph.edges.length,
|
|
9
|
+
}
|
|
10
|
+
: null,
|
|
11
|
+
diagnostics: report.diagnostics,
|
|
12
|
+
findings: report.findings,
|
|
13
|
+
remediation: report.remediation,
|
|
14
|
+
summary: report.summary,
|
|
15
|
+
};
|
|
16
|
+
return JSON.stringify(serializable, null, 2);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=json-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-reporter.js","sourceRoot":"","sources":["../../src/output/json-reporter.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,MAA2D;IACtF,MAAM,YAAY,GAAG;QACnB,GAAG,MAAM;QACT,KAAK,EAAE,MAAM,CAAC,KAAK;YACjB,CAAC,CAAC;gBACE,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY;gBACvC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI;gBAClC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM;aACrC;YACH,CAAC,CAAC,IAAI;QACR,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-reporter.d.ts","sourceRoot":"","sources":["../../src/output/markdown-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,CA+BxF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function toMarkdownReport(report, ownership) {
|
|
2
|
+
const lines = ["# audit-trace report", ""];
|
|
3
|
+
lines.push(`## Findings (${report.findings.length})`);
|
|
4
|
+
for (const f of report.findings) {
|
|
5
|
+
lines.push(`- **${f.severity.toUpperCase()}** \`${f.packageName}\` — ${f.title ?? f.id}`);
|
|
6
|
+
}
|
|
7
|
+
lines.push("");
|
|
8
|
+
lines.push("## Ownership paths");
|
|
9
|
+
for (const o of ownership.slice(0, 50)) {
|
|
10
|
+
lines.push(`- \`${o.packageName}\` (${o.severity}) — top-level via **${o.topLevelNames.join(", ") || "?"}** — dev: ${o.isDevDependency}`);
|
|
11
|
+
}
|
|
12
|
+
if (ownership.length > 50)
|
|
13
|
+
lines.push(`… and ${ownership.length - 50} more`);
|
|
14
|
+
lines.push("");
|
|
15
|
+
lines.push("## Remediation");
|
|
16
|
+
for (const r of report.remediation) {
|
|
17
|
+
lines.push(`- **${r.kind}** ${r.targetPackage}: ${r.reason}`);
|
|
18
|
+
if (r.manifestPatch)
|
|
19
|
+
lines.push("```json\n" + JSON.stringify(r.manifestPatch, null, 2) + "\n```");
|
|
20
|
+
}
|
|
21
|
+
lines.push("");
|
|
22
|
+
lines.push("## CI diagnostics");
|
|
23
|
+
for (const d of report.diagnostics ?? []) {
|
|
24
|
+
lines.push(`- **${d.code}** (${d.severity}): ${d.message}`);
|
|
25
|
+
}
|
|
26
|
+
return lines.join("\n");
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=markdown-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-reporter.js","sourceRoot":"","sources":["../../src/output/markdown-reporter.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,gBAAgB,CAAC,MAAmB,EAAE,SAA0B;IAC9E,MAAM,KAAK,GAAa,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;IAErD,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACtD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,WAAW,QAAQ,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5F,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QACvC,KAAK,CAAC,IAAI,CACR,OAAO,CAAC,CAAC,WAAW,OAAO,CAAC,CAAC,QAAQ,uBAAuB,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC,CAAC,eAAe,EAAE,CAC9H,CAAC;IACJ,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,GAAG,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC;IAE7E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,aAAa;YACjB,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DependencyGraphSnapshot, VulnerabilityFinding } from "../core/models.js";
|
|
2
|
+
import type { OwnershipPath } from "../core/ownership/tracer.js";
|
|
3
|
+
export declare function renderPretty(findings: VulnerabilityFinding[], ownership: OwnershipPath[], graph: DependencyGraphSnapshot | null, opts: {
|
|
4
|
+
ci?: boolean;
|
|
5
|
+
verbose?: boolean;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function printCiSummary(diagnostics: import("../core/models.js").CiDiagnostic[], verbose: boolean): string;
|
|
8
|
+
//# sourceMappingURL=terminal-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-renderer.d.ts","sourceRoot":"","sources":["../../src/output/terminal-renderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAIjE,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,oBAAoB,EAAE,EAChC,SAAS,EAAE,aAAa,EAAE,EAC1B,KAAK,EAAE,uBAAuB,GAAG,IAAI,EACrC,IAAI,EAAE;IAAE,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACxC,MAAM,CA+BR;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,OAAO,mBAAmB,EAAE,YAAY,EAAE,EACvD,OAAO,EAAE,OAAO,GACf,MAAM,CAWR"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { formatPathNames, buildIndexes, shortestPathFromRoots } from "../core/graph-engine/traverse.js";
|
|
3
|
+
import { formatChain } from "./tree-format.js";
|
|
4
|
+
export function renderPretty(findings, ownership, graph, opts) {
|
|
5
|
+
const lines = [];
|
|
6
|
+
lines.push(chalk.bold("audit-trace"));
|
|
7
|
+
lines.push("");
|
|
8
|
+
for (const f of findings) {
|
|
9
|
+
const label = chalk.hex(f.severity === "critical" ? "#ff0000" : "#ffa500");
|
|
10
|
+
lines.push(label(`[${f.severity.toUpperCase()}] ${f.packageName}`));
|
|
11
|
+
if (f.title)
|
|
12
|
+
lines.push(` ${f.title}`);
|
|
13
|
+
}
|
|
14
|
+
lines.push("");
|
|
15
|
+
lines.push(chalk.bold("Ownership paths"));
|
|
16
|
+
for (const o of ownership.slice(0, 40)) {
|
|
17
|
+
if (!graph) {
|
|
18
|
+
lines.push(`- ${o.packageName}`);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const idx = buildIndexes(graph);
|
|
22
|
+
const path = shortestPathFromRoots(graph, idx, o.nodeId);
|
|
23
|
+
if (path) {
|
|
24
|
+
const names = path.map((id) => graph.nodes.get(id)?.name ?? id);
|
|
25
|
+
lines.push(formatChain(names));
|
|
26
|
+
lines.push("");
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
lines.push(`- ${formatPathNames(o.pathNodeIds, graph.nodes)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (opts.ci && !opts.verbose) {
|
|
33
|
+
lines.push("");
|
|
34
|
+
lines.push(chalk.dim("Run with --ci-verbose for filter and graph context."));
|
|
35
|
+
}
|
|
36
|
+
return lines.join("\n");
|
|
37
|
+
}
|
|
38
|
+
export function printCiSummary(diagnostics, verbose) {
|
|
39
|
+
const lines = [];
|
|
40
|
+
lines.push(chalk.bold("CI summary"));
|
|
41
|
+
for (const d of diagnostics) {
|
|
42
|
+
const col = d.severity === "error" ? chalk.red : d.severity === "warn" ? chalk.yellow : chalk.blue;
|
|
43
|
+
lines.push(col(`[${d.code}] ${d.message}`));
|
|
44
|
+
if (verbose && d.detail)
|
|
45
|
+
lines.push(chalk.dim(d.detail));
|
|
46
|
+
if (verbose && d.remediationHint)
|
|
47
|
+
lines.push(chalk.green(`Hint: ${d.remediationHint}`));
|
|
48
|
+
}
|
|
49
|
+
return lines.join("\n");
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=terminal-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-renderer.js","sourceRoot":"","sources":["../../src/output/terminal-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-format.d.ts","sourceRoot":"","sources":["../../src/output/tree-format.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAQnD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Pretty-print a dependency chain like npm ls / user example. */
|
|
2
|
+
export function formatChain(names) {
|
|
3
|
+
if (names.length === 0)
|
|
4
|
+
return "";
|
|
5
|
+
let s = names[0];
|
|
6
|
+
for (let i = 1; i < names.length; i++) {
|
|
7
|
+
const pad = " ".repeat(i - 1);
|
|
8
|
+
s += `\n${pad}└── ${names[i]}`;
|
|
9
|
+
}
|
|
10
|
+
return s;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=tree-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-format.js","sourceRoot":"","sources":["../../src/output/tree-format.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,UAAU,WAAW,CAAC,KAAe;IACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,CAAC,IAAI,KAAK,GAAG,OAAO,KAAK,CAAC,CAAC,CAAE,EAAE,CAAC;IAClC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,CAEnD;AAED,wBAAgB,UAAU,IAAI,WAAW,EAAE,CAE1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,GAAkB,EAAE,CAAC;AAElC,MAAM,UAAU,cAAc,CAAC,CAAc;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AuditReport, CiDiagnostic, DependencyGraphSnapshot, VulnerabilityFinding } from "../core/models.js";
|
|
2
|
+
import type { OwnershipPath } from "../core/ownership/tracer.js";
|
|
3
|
+
export interface AuditPlugin {
|
|
4
|
+
name: string;
|
|
5
|
+
afterGraphBuilt?(graph: DependencyGraphSnapshot): void;
|
|
6
|
+
afterAuditNormalized?(findings: VulnerabilityFinding[]): void;
|
|
7
|
+
onCiDiagnostics?(diagnostics: CiDiagnostic[]): CiDiagnostic[] | void;
|
|
8
|
+
formatReport?(report: AuditReport, ownership: OwnershipPath[]): AuditReport | void;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACvD,oBAAoB,CAAC,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC;IAC9D,eAAe,CAAC,CAAC,WAAW,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC;IACrE,YAAY,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,WAAW,GAAG,IAAI,CAAC;CACpF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Example: run audit-trace in GitHub Actions
|
|
2
|
+
#
|
|
3
|
+
# Install the CLI in your workflow (pick one):
|
|
4
|
+
# - npm install -g audit-trace (after publishing to npm)
|
|
5
|
+
# - npm ci && npm install ../path-to/audit-trace && use node_modules/.bin/audit-trace
|
|
6
|
+
# - checkout this repo, npm ci && npm run build && node dist/cli.js ...
|
|
7
|
+
|
|
8
|
+
name: audit-trace-example
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
workflow_dispatch: {}
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
deps:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: "20"
|
|
21
|
+
- run: npm ci
|
|
22
|
+
- name: audit-trace report
|
|
23
|
+
run: |
|
|
24
|
+
if command -v audit-trace >/dev/null 2>&1; then
|
|
25
|
+
audit-trace report --ci --json --fail-on high | tee audit-trace-report.json
|
|
26
|
+
else
|
|
27
|
+
echo "Install audit-trace first; see examples/github-actions/ci.yml header."
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
- name: Job summary from diagnostics
|
|
31
|
+
if: always() && hashFiles('audit-trace-report.json') != ''
|
|
32
|
+
run: |
|
|
33
|
+
echo "## audit-trace" >> "$GITHUB_STEP_SUMMARY"
|
|
34
|
+
node -e "const r=require('./audit-trace-report.json');(r.diagnostics||[]).forEach(d=>console.log('- **'+d.code+'**: '+d.message));" >> "$GITHUB_STEP_SUMMARY" || true
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "audit-trace",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Dependency vulnerability analysis with ownership tracing and actionable remediation",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"audit-trace": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"examples"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"start": "node dist/cli.js",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"prepack": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"audit",
|
|
27
|
+
"security",
|
|
28
|
+
"npm",
|
|
29
|
+
"pnpm",
|
|
30
|
+
"yarn",
|
|
31
|
+
"dependencies",
|
|
32
|
+
"cli"
|
|
33
|
+
],
|
|
34
|
+
"author": "",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@yarnpkg/lockfile": "^1.1.0",
|
|
38
|
+
"chalk": "^5.3.0",
|
|
39
|
+
"commander": "^12.1.0",
|
|
40
|
+
"debug": "^4.4.0",
|
|
41
|
+
"graphlib": "^2.1.8",
|
|
42
|
+
"ink": "^5.0.1",
|
|
43
|
+
"madge": "^8.0.0",
|
|
44
|
+
"ora": "^8.1.1",
|
|
45
|
+
"react": "^18.3.1",
|
|
46
|
+
"semver": "^7.6.3",
|
|
47
|
+
"treeify": "^1.1.0",
|
|
48
|
+
"yaml": "^2.6.1"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/graphlib": "^2.1.12",
|
|
52
|
+
"@types/node": "^22.10.2",
|
|
53
|
+
"@types/react": "^18.3.12",
|
|
54
|
+
"@types/semver": "^7.5.8",
|
|
55
|
+
"typescript": "^5.7.2",
|
|
56
|
+
"vitest": "^2.1.8"
|
|
57
|
+
}
|
|
58
|
+
}
|