Summary
playground has 19 high-severity dependency advisories. The CI gate that would
have caught them exists, runs pnpm audit --audit-level=high, and never
executes — so the check reports green while the findings accumulate.
This is the #2447 pattern again, but on the security audit rather than the test
suites, which is why it has been invisible for longer.
The gate, and why it is dead
# .github/workflows/test.yml:270
- name: Run security audit
run: pnpm audit --audit-level=high
That step is inside the security-tests job (test.yml:242). Every PR shows:
Unit Tests: SKIPPED Integration Tests: SKIPPED
Security Tests: SKIPPED Coverage Gate: SKIPPED
✅ Merge Gate: SUCCESS
security-tests is gated on packages/*, which no longer exists on playground
or main — the file says so itself, a few lines below the job:
The app's own suite (2702 tests). Every other test job above is gated on
packages/*, which no longer exists on playground or main …
#2450 fixed that for the app suite. security-tests was left behind, and it
is the job carrying the dependency audit.
Current findings
pnpm audit --audit-level=high on playground:
44 vulnerabilities found
Severity: 3 low | 23 moderate | 18 high (1 ignored)
(19 high before #2501, which closes brace-expansion.)
High findings span:
| package |
likely remediation |
brace-expansion |
override — done in #2501 |
fast-uri |
override |
ip-address |
override |
postcss |
override |
socket.io-parser |
override |
undici |
may need a transitive-parent upgrade |
sharp |
likely a real upgrade |
next |
framework upgrade — needs its own assessment |
I have deliberately not bundled these. next and sharp are not one-line
overrides, and an override that pins a framework transitively is its own risk.
Suggested direction
- Make the gate run. Whatever
security-tests becomes, the audit step needs
to execute on PRs — otherwise this recurs silently. Note it will fail
immediately, so it likely wants to land after (or alongside) the override
batch, or start non-blocking with a deadline.
- Batch the override-able ones (
fast-uri, ip-address, postcss,
socket.io-parser) — mechanical, one PR.
- Assess
next / sharp / undici separately — real upgrades with real
blast radius.
Note on overrides as a mitigation
brace-expansion illustrates the failure mode worth designing against: the repo
already had an override (>=5.0.7 <6), added for an earlier advisory. A newer
advisory then raised the patched floor past it, and the <6 ceiling guaranteed
the pin could not drift forward on its own. An override is a point-in-time
assertion; it does not stay true. Ceilings on security floors are worth avoiding,
and a running audit is what catches the ones that go stale anyway.
Same class was live in percolator-indexer (fixed in indexer#193) — and there it
was CI-blocking, because that repo's audit gate does run.
Summary
playgroundhas 19 high-severity dependency advisories. The CI gate that wouldhave caught them exists, runs
pnpm audit --audit-level=high, and neverexecutes — so the check reports green while the findings accumulate.
This is the #2447 pattern again, but on the security audit rather than the test
suites, which is why it has been invisible for longer.
The gate, and why it is dead
That step is inside the
security-testsjob (test.yml:242). Every PR shows:security-testsis gated onpackages/*, which no longer exists onplaygroundor
main— the file says so itself, a few lines below the job:#2450 fixed that for the app suite.
security-testswas left behind, and itis the job carrying the dependency audit.
Current findings
pnpm audit --audit-level=highonplayground:(19 high before #2501, which closes
brace-expansion.)High findings span:
brace-expansionfast-uriip-addresspostcsssocket.io-parserundicisharpnextI have deliberately not bundled these.
nextandsharpare not one-lineoverrides, and an override that pins a framework transitively is its own risk.
Suggested direction
security-testsbecomes, the audit step needsto execute on PRs — otherwise this recurs silently. Note it will fail
immediately, so it likely wants to land after (or alongside) the override
batch, or start non-blocking with a deadline.
fast-uri,ip-address,postcss,socket.io-parser) — mechanical, one PR.next/sharp/undiciseparately — real upgrades with realblast radius.
Note on overrides as a mitigation
brace-expansionillustrates the failure mode worth designing against: the repoalready had an override (
>=5.0.7 <6), added for an earlier advisory. A neweradvisory then raised the patched floor past it, and the
<6ceiling guaranteedthe pin could not drift forward on its own. An override is a point-in-time
assertion; it does not stay true. Ceilings on security floors are worth avoiding,
and a running audit is what catches the ones that go stale anyway.
Same class was live in percolator-indexer (fixed in indexer#193) — and there it
was CI-blocking, because that repo's audit gate does run.