import { mkdtemp, rm, writeFile } from
"node:fs/promises" ;
import { tmpdir } from
"node:os" ;
import path from
"node:path" ;
import { describe, expect, it } from
"vitest" ;
import {
collectProdResolvedPackagesFromLockfile,
createBulkAdvisoryPayload,
filterFindingsBySeverity,
parseSnapshotKey,
runPnpmAuditProd,
stripVersionDecorators,
} from
"../../scripts/pre-commit/pnpm-audit-prod.mjs" ;
describe(
"pnpm-audit-prod" , () => {
it(
"parses scoped snapshot keys with peer suffixes" , () => {
expect(parseSnapshotKey(
"@scope/pkg@1.2.3(peer@4.5.6)" )).toEqual({
packageName:
"@scope/pkg" ,
reference:
"1.2.3(peer@4.5.6)" ,
version:
"1.2.3" ,
});
});
it(
"strips peer and patch decorators from resolved versions" , () => {
expect(stripVersionDecorators(
"7.0.0-rc.9(patch_hash=abc123)(sharp@0.34.5)" )).to
Be(
"7.0.0-rc.9" ,
);
expect(stripVersionDecorators("1.2.3" )).toBe("1.2.3" );
});
it("collects the production graph from pnpm lockfile snapshots" , () => {
const lockfile = `lockfileVersion: '9.0'
importers:
.:
dependencies:
pkg-a:
version: 1 .0 .0
devDependencies:
dev-only:
version: 9 .9 .9
extensions/demo:
dependencies:
'@scope/pkg' :
version: 2 .0 .0 (peer@4 .0 .0 )
workspace-lib:
version: link:../../packages/workspace-lib
snapshots:
pkg-a@1 .0 .0 :
dependencies:
transitive: 3 .0 .0 (patch_hash=abc123)
transitive@3 .0 .0 (patch_hash=abc123): {}
'@scope/pkg@2.0.0(peer@4.0.0)' :
optionalDependencies:
opt-dep: 4 .0 .0
opt-dep@4 .0 .0 : {}
`;
const payload = createBulkAdvisoryPayload(collectProdResolvedPackagesFromLockfile(lockfile));
expect(payload).toEqual({
"@scope/pkg" : ["2.0.0" ],
"opt-dep" : ["4.0.0" ],
"pkg-a" : ["1.0.0" ],
transitive: ["3.0.0" ],
});
});
it("resolves npm alias snapshots to the real package name" , () => {
const lockfile = `lockfileVersion: '9.0'
importers:
.:
dependencies:
request:
version: npm:@cypress/request@3 .0 .10
snapshots:
'@cypress/request@3.0.10' : {}
`;
const payload = createBulkAdvisoryPayload(collectProdResolvedPackagesFromLockfile(lockfile));
expect(payload).toEqual({
"@cypress/request" : ["3.0.10" ],
});
});
it("reads inline importer dependency maps without repo dependencies" , () => {
const lockfile = `lockfileVersion: '9.0'
importers:
.:
dependencies:
axios: {specifier: ^1 .0 .0 , version: 1 .0 .0 }
'@scope/pkg' : {'version' : '2.0.0(peer@4.0.0)' }
snapshots:
axios@1 .0 .0 : {}
'@scope/pkg@2.0.0(peer@4.0.0)' : {}
`;
const payload = createBulkAdvisoryPayload(collectProdResolvedPackagesFromLockfile(lockfile));
expect(payload).toEqual({
"@scope/pkg" : ["2.0.0" ],
axios: ["1.0.0" ],
});
});
it("resolves quoted snapshot keys that contain tarball URLs" , () => {
const lockfile = `lockfileVersion: '9.0'
importers:
.:
dependencies:
wrapper:
version: 1 .0 .0
snapshots:
wrapper@1 .0 .0 :
dependencies:
libsignal: '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/abc123 '
'@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/abc123 ':
dependencies:
curve25519-js: 0 .0 .4
curve25519-js@0 .0 .4 : {}
`;
const payload = createBulkAdvisoryPayload(collectProdResolvedPackagesFromLockfile(lockfile));
expect(payload).toEqual({
"@whiskeysockets/libsignal-node" : [
"https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/abc123 ",
],
"curve25519-js" : ["0.0.4" ],
wrapper: ["1.0.0" ],
});
});
it("filters advisory findings by minimum severity" , () => {
const findings = filterFindingsBySeverity(
{
axios: [
{
id: "GHSA-low" ,
severity: "moderate" ,
title: "moderate issue" ,
},
{
id: "GHSA-high" ,
severity: "high" ,
title: "high issue" ,
url: "https://github.com/advisories/GHSA-high ",
},
],
},
"high" ,
);
expect(findings).toEqual([
{
id: "GHSA-high" ,
packageName: "axios" ,
severity: "high" ,
title: "high issue" ,
url: "https://github.com/advisories/GHSA-high ",
vulnerableVersions: null ,
},
]);
});
it("returns a failing exit code when bulk advisories include high severity findings" , async () => {
const tempDir = await mkdtemp(path.join(tmpdir(), "openclaw-audit-prod-" ));
await writeFile(
path.join(tempDir, "pnpm-lock.yaml" ),
`lockfileVersion: '9.0'
importers:
.:
dependencies:
axios:
version: 1 .0 .0
snapshots:
axios@1 .0 .0 : {}
`,
"utf8" ,
);
try {
const stdoutChunks: string[] = [];
const stderrChunks: string[] = [];
const exitCode = await runPnpmAuditProd({
rootDir: tempDir,
fetchImpl: async () =>
new Response(
JSON.stringify({
axios: [
{
id: "GHSA-test" ,
severity: "high" ,
title: "test issue" ,
vulnerable_versions: "<=1.0.0" ,
url: "https://github.com/advisories/GHSA-test ",
},
],
}),
{
status: 200 ,
headers: {
"content-type" : "application/json" ,
},
},
),
stdout: {
write(chunk: string) {
stdoutChunks.push(chunk);
return true ;
},
} as NodeJS.WriteStream,
stderr: {
write(chunk: string) {
stderrChunks.push(chunk);
return true ;
},
} as NodeJS.WriteStream,
});
expect(exitCode).toBe(1 );
expect(stdoutChunks).toEqual([]);
expect(stderrChunks.join("" )).toContain("Found 1 high or higher advisories" );
} finally {
await rm(tempDir, { recursive: true , force: true });
}
});
});
Messung V0.5 in Prozent C=98 H=100 G=98
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-06-04)
¤
*© Formatika GbR, Deutschland