import { mkdtemp, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { describe, expect, it } from "vitest"; import { classifyVulnerabilityFindings, renderDependencyVulnerabilityGateMarkdownReport, runDependencyVulnerabilityGate, } from "../../scripts/dependency-vulnerability-gate.mjs"; function advisory({ id, severity, title, vulnerableVersions = "<=1.0.0", }: { id: string; severity: string; title: string; vulnerableVersions?: string; }) { return { id, severity, title, vulnerable_versions: vulnerableVersions, url: `https://github.com/advisories/${id}`, }; } async function writeLockfile(rootDir: string) { await writeFile( path.join(rootDir, "pnpm-lock.yaml"), `lockfileVersion: '9.0' importers: .: dependencies: runtime-high: version: 1.0.0 devDependencies: dev-high: version: 1.0.0 snapshots: runtime-high@1.0.0: {} dev-high@1.0.0: {} transitive-critical@1.0.0: {} `, "utf8", ); } describe("dependency-vulnerability-gate", () => { it("blocks critical advisories anywhere and high advisories in the production graph", () => { const result = classifyVulnerabilityFindings({ allAdvisories: { "dev-high": [advisory({ id: "GHSA-dev-high", severity: "high", title: "dev high" })], "transitive-critical": [ advisory({ id: "GHSA-critical", severity: "critical", title: "critical issue" }), ], }, productionAdvisories: { "runtime-high": [ advisory({ id: "GHSA-runtime-high", severity: "high", title: "runtime high" }), ], }, }); expect(result.blockers.map((finding) => finding.id)).toEqual([ "GHSA-critical", "GHSA-runtime-high", ]); expect(result.findings.map((finding) => finding.id)).toEqual([ "GHSA-critical", "GHSA-dev-high", "GHSA-runtime-high", ]); }); it("blocks malware advisories regardless of severity or graph", () => { const result = classifyVulnerabilityFindings({ allAdvisories: { dev: [advisory({ id: "GHSA-malware", severity: "low", title: "Malware in dev" })], }, productionAdvisories: {}, }); expect(result.blockers).toMatchObject([ { id: "GHSA-malware", malware: true, severity: "low", }, ]); }); it("queries full and production lockfile graphs separately", async () => { const rootDir = await mkdtemp(path.join(tmpdir(), "openclaw-vuln-gate-")); await writeLockfile(rootDir); const payloads: Record[] = []; const report = await runDependencyVulnerabilityGate({ rootDir, fetchImpl: async (_url, init) => { const payload = JSON.parse(String(init?.body)); payloads.push(payload); const packages = Object.keys(payload); const body: Record = {}; if (packages.includes("runtime-high")) { body["runtime-high"] = [ advisory({ id: "GHSA-runtime-high", severity: "high", title: "runtime high" }), ]; } if (packages.includes("dev-high")) { body["dev-high"] = [ advisory({ id: "GHSA-dev-high", severity: "high", title: "dev high" }), ]; } return new Response(JSON.stringify(body), { status: 200, headers: { "content-type": "application/json" }, }); }, }); expect(payloads).toHaveLength(2); expect(payloads[0]).toEqual({ "dev-high": ["1.0.0"], "runtime-high": ["1.0.0"], "transitive-critical": ["1.0.0"], }); expect(payloads[1]).toEqual({ "runtime-high": ["1.0.0"], }); expect(report.blockers.map((finding) => finding.id)).toEqual(["GHSA-runtime-high"]); expect(report.findings.map((finding) => finding.id)).toEqual([ "GHSA-dev-high", "GHSA-runtime-high", ]); }); it("documents the resolved transitive dependency graph scope in Markdown", () => { const markdown = renderDependencyVulnerabilityGateMarkdownReport({ generatedAt: "2026-05-12T00:00:00.000Z", policy: { blocks: [ "known malware advisories anywhere in the installed graph", "critical advisories anywhere in the installed graph", "high advisories in the production/runtime graph", ], reports: [ "moderate and lower advisories", "high advisories outside production/runtime graph", ], vulnerabilityExceptions: false, }, graphs: { all: { packages: 2, packageVersions: 2 }, production: { packages: 1, packageVersions: 1 }, }, blockers: [], findings: [], }); expect(markdown).toContain("# npm Advisory Vulnerability Gate: Resolved Dependency Graph"); expect(markdown).toContain("## Scope"); expect(markdown).toContain("resolved package versions from pnpm-lock.yaml"); expect(markdown).toContain("It includes transitive dependencies."); }); });