Files
pulse/scripts
rcourtman 06a68dbff3 Warn on inherited npm advisories when the lockfile is unchanged (#2442)
Since 3 October the required Frontend check has failed on every open
pull request, including Go-only ones, because of GHSA-vfj7-8cjw-p6xm
(`braces` <= 3.0.3, high, no patched release). `braces` reaches the
frontend graph only through dev-only `tailwindcss` 3 and `jscpd` 4. `npm
audit --omit=dev` is clean, so the shipped bundle is not affected.

A pull request that leaves `package.json` and `package-lock.json`
untouched has the same dependency graph as its base commit. It can
neither add a finding nor remove one, so failing it blocks every fix
without making anything safer.

## What changes

`scripts/npm-audit-retry.sh` now treats findings the same way it already
treated an unreachable advisory endpoint:

- **The change moves the dependency graph, or edits the runner**
(`NPM_AUDIT_REQUIRE_RESULT=true`): any finding at any severity fails, as
before. A missing answer also fails.
- **The graph is the base commit's** (`NPM_AUDIT_REQUIRE_RESULT=false`):
the run warns instead, still naming every finding. A missing answer also
only warns, as before.
- **Only an explicit `false` relaxes the verdict.** An empty or
unrecognised value stays strict. This also tightens the outage path,
which previously relaxed on any value other than `true`.

The scheduled `npm-audit` scan and the daily dependency advisory watch
keep the strict default. An inherited advisory therefore still fails
once a day until the graph is fixed; `test_dependency_advisory_watch.py`
now proves this. No severity threshold, allowlist or suppression is
added.

## Landing

This change edits the runner, so its own Frontend audit runs in strict
mode and fails on this same advisory. It cannot pass the required
checks, so it lands only by an explicit maintainer merge. That is
intentional: the policy is relaxed by a human decision, never by a
change passing its own check.

Removing `braces` for real means migrating to Tailwind 4 and jscpd
5.4.0; that is tracked separately. Dependency PRs (#2352, #2278) stay
blocked until that lands.

## Verification

- `scripts/tests/test-npm-audit-retry.sh`: 19 cases pass.
- `test_npm_audit_retry.py` and `test_dependency_advisory_watch.py`
pass.
- `TestFrontendDependencySecurityAuditsAreRequired` passes.
- `check_workflow_trust.py` passes.
- The real runner against main's lockfile exits 0 with the warning and
all 7 findings named when `NPM_AUDIT_REQUIRE_RESULT=false`, and exits 1
with `::error::` when it is `true`.
2026-10-03 22:41:14 +01:00
..
…
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
…
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-09-01 21:37:41 +01:00
2026-08-29 22:12:41 +01:00
2026-03-18 16:06:30 +00:00