Skip to content

fix(deps): clear GHSA-mw96-cpmx-2vgc by upgrading rollup - #12

Merged
andreszorro merged 1 commit into
mainfrom
fix/rollup-advisory
Aug 17, 2026
Merged

fix(deps): clear GHSA-mw96-cpmx-2vgc by upgrading rollup#12
andreszorro merged 1 commit into
mainfrom
fix/rollup-advisory

Conversation

@andreszorro

Copy link
Copy Markdown
Collaborator

pnpm audit: 1 high → no known vulnerabilities.

The pin was protecting against something narrower than we thought

rollup was held at 4.52.5 because ≥4.53.0 panics — called Option::unwrap() on a None value — on input scripts/escapes.test.js feeds the parser, and the fix for this advisory lands in 4.59.0.

Rather than take that on faith, I mapped the panic on 4.59.0. It needs all three of:

  1. a directive prologue (a string-literal statement at the start of a body),
  2. holding an escape sequence rather than a raw code unit,
  3. that is a lone surrogate.
Input 4.59.0
"\uD800"; as the first statement panics
the same, as a raw surrogate character ok
let x; "\uD800"; (not a directive) ok
variable initializer, object value, property key, import specifier, template literal ok

A directive prologue holding a lone-surrogate escape is not a shape a bundler emits — real ones are "use strict". So the pin was buying nothing that mattered and costing a High advisory.

What changed

  • rollup 4.52.54.62.4. pnpm why rollup shows a single version, used by vite@7.3.6.
  • parseAst is now called through a wrapper that turns a parser failure into the same refusal as anything else this module cannot handle. That is the module's existing contract — refuse rather than emit an artifact the upload would reject — so an unreadable bundle fails closed with a legible message instead of an unexplained Rust panic.
  • The directive-prologue test asserts the guarantee, not the wording. That input was always destined for a refusal, because a directive is not a value position; only which check reaches it first has changed. A new test covers the fail-closed path directly.
  • The renovate rule disabling rollup updates is removed, since it would otherwise have held rollup at a vulnerable version indefinitely.

Verified

pnpm audit → no known vulnerabilities · 381/381 tests · biome ci clean · tsc --noEmit clean · renovate config validates.

And the thing escapes.js exists for, checked on the new parser rather than assumed — a real single-file render, read back through findUnspellable:

index.html      1,020,478 bytes  |  unspellable units: 0
artifact.html   1,019,541 bytes  |  unspellable units: 0

🤖 Generated with Claude Code

rollup was held at 4.52.5 because 4.53.0 and above panic — `called
Option::unwrap() on a None value` — on input scripts/escapes.test.js feeds the
parser, and the patched version for this advisory is 4.59.0.

Mapping the panic showed it is far narrower than the note claimed. It needs all
three of: a directive prologue, holding an escape *sequence* rather than a raw
code unit, that is a lone surrogate. A raw surrogate parses. The same escape in
a variable initializer, an object value, a property key, an import specifier or
a template literal parses. Only `"\\uD800";` as the first statement does not,
which is not a shape a bundler emits.

So the pin bought nothing that mattered and cost a High advisory. rollup is now
4.62.4 and `pnpm audit` reports no known vulnerabilities.

The parser is now called through a wrapper that turns a failure into the same
refusal as anything else this module cannot handle. That is the existing design
— refuse rather than emit an artifact the upload would reject — and it means an
unreadable bundle fails closed with a legible message instead of an unexplained
Rust panic. The directive-prologue case was already destined for a refusal,
since a directive is not a value position; only which check gets there first
has changed, so its test now asserts the guarantee rather than the wording.

Also removes the renovate rule that disabled rollup updates entirely, which
would otherwise have held it at a vulnerable version forever.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@andreszorro
andreszorro merged commit 2081b86 into main Aug 17, 2026
10 checks passed
@upwind-code-us

upwind-code-us Bot commented Aug 17, 2026

Copy link
Copy Markdown

Upwind Upwind Code Scan - ✅ Proceed with Deployment

0 newly introduced vulnerabilities · 1 resolved · 0 total in this PR vs main


Resolved · 1 finding
CVE Package Version
CVE-2026-27606 rollup 4.52.5

View full analysis in Upwind Console

Scan completed in 40s

Scan history (1 scan)
Commit Scanned at New Resolved Net
38ed5d8 < 2026-08-17 01:15 UTC 0 -1 -1

Last scanned: 38ed5d8 · 2026-08-17 01:15 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant