Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.d/fixed-523-npm-audit-gate-package-scope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- The npm audit gate documents the optional `package` exception field, treats an
empty `package` as unscoped, and names the package in unused-exception
warnings (hivecommons/docs#523, #524, #525).
10 changes: 9 additions & 1 deletion scripts/npm-audit-gate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ describe("evaluateAudit", () => {
expect(r.blocking).toEqual([]);
});

it("treats an empty package as an unscoped exception", () => {
const r = evaluateAudit(REPORT, [exception({ package: "" })], "high", NOW);
expect(r.blocking).toEqual([]);
expect(r.unused).toEqual([]);
});

it("does not apply an exception scoped to a different package", () => {
const r = evaluateAudit(
REPORT,
Expand Down Expand Up @@ -416,7 +422,9 @@ describe("main", () => {
expect(exitSpy).not.toHaveBeenCalled();
const out = logSpy.mock.calls.flat().join("\n");
expect(out).toMatch(/Acknowledged 1 advisory/);
expect(out).toMatch(/::warning::Unused npm audit exception GHSA-zzzz/);
expect(out).toMatch(
/::warning::Unused npm audit exception GHSA-zzzz-zzzz-zzzz \(nope\)/
);
expect(out).toMatch(/Ignoring 1 advisory/);
expect(out).toMatch(/passed at level "high"/);
});
Expand Down
11 changes: 9 additions & 2 deletions scripts/npm-audit-gate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
* expired exception fails the gate so acknowledged findings are re-reviewed
* rather than silently forgotten.
*
* An exception may also carry an optional `package` that scopes it to one
* affected package, so one GHSA can be listed once per package. Without
* `package` (or with an empty one) the exception covers that GHSA for every
* package.
*
* A file that is not an audit report (e.g. the error document npm writes when
* the registry is unreachable) fails the gate rather than passing it.
*
Expand Down Expand Up @@ -124,7 +129,7 @@ export interface GateResult {
}

function exceptionKey(id: string, pkg?: string): string {
return `${id.toUpperCase()}:${pkg ?? "*"}`;
return `${id.toUpperCase()}:${pkg || "*"}`;
}

export function evaluateAudit(
Expand Down Expand Up @@ -240,7 +245,9 @@ export function main(argv: string[] = process.argv.slice(2)): void {
);
}
for (const ex of result.unused) {
console.log(`::warning::Unused npm audit exception ${ex.id} — remove it.`);
console.log(
`::warning::Unused npm audit exception ${ex.id} (${ex.package || "*"}) — remove it.`
);
}

let failed = false;
Expand Down
Loading