Skip to content

Hotfix: SSRF + CVE patches + audit cleanup to production#46

Merged
MP2EZ merged 2 commits into
mainfrom
preview
May 31, 2026
Merged

Hotfix: SSRF + CVE patches + audit cleanup to production#46
MP2EZ merged 2 commits into
mainfrom
preview

Conversation

@MP2EZ
Copy link
Copy Markdown
Owner

@MP2EZ MP2EZ commented May 31, 2026

Production cutover — security patches + audit cleanup

Two commits since the last `preview → main` cutover:

Why ship now

#44 patches a live SSRF in `@opennextjs/cloudflare` (the Cloudflare Workers server adapter currently running being.fyi) via `/cdn-cgi/` path-normalization bypass (GHSA-c7mq-gh6q-6q7c), plus next.js high-severity CVEs (Server-Actions CSRF, middleware bypass, RSC cache poisoning) that target the live middleware GPC/AB surface. The site is in production; these reach real traffic. Worth promoting promptly.

What ships

Security (#44)

Package From To
`@opennextjs/cloudflare` 1.14.4 1.19.11 (SSRF fix)
`next` 16.0.10 16.2.6 (high-sev set)
`eslint-config-next` 16.0.7 16.2.6
  • 51 → 4 npm vulns (remaining 4 are build-chain moderates whose only "fix" is a catastrophic downgrade — left intentionally; do not `npm audit fix --force`)
  • CI runner Node 20 → 22 (the upgraded transitive wrangler requires Node 22; surfaced as a wrangler-smoke failure, fixed in-PR)

Cleanup (#45)

  • −121 LOC dead scaffolding (`trackConversion`, `getGpcFromCookie`, `POSTHOG_ASSETS_HOST`, phase-2 comments) — paths the architecture deliberately doesn't use
  • Perf: middleware now only clears `being_gpc` when the cookie is actually present, instead of emitting a `Set-Cookie` on every no-GPC request (which defeats shared/CDN caching of HTML responses)
  • `.gitignore`: added `/.open-next/` (build output was untracked-but-not-ignored)

Already verified on preview

Auto-fires post-merge

  • Deploy → Cloudflare Workers production
  • Post-deploy smoke → curls being.fyi/home, /download, /privacy (fails loudly on regression)

No behavior change for users

PostHog analytics (live since the prior cutover) is unaffected. The middleware GPC/AB logic is functionally identical (the cookie-clear guard only changes when a redundant Set-Cookie is emitted, not the GPC outcome). This is a security + internal-cleanup release.

Outstanding (separate, your action)

  • SEC-02 — waitlist rate limiting: best as a Cloudflare WAF rule (dashboard, keyed on `CF-Connecting-IP`). Not code; flagging for follow-up now that the site is live.

🤖 Generated with Claude Code

MP2EZ and others added 2 commits May 31, 2026 11:44
* fix(security): patch SSRF + high-severity CVEs in next + OpenNext

Audit (/m:audit --security) flagged 51 npm vulns, 2 hitting the
production runtime:

- @opennextjs/cloudflare 1.14.4 → 1.19.11: SSRF via /cdn-cgi/
  path-normalization bypass (GHSA-c7mq-gh6q-6q7c). This is the live
  Cloudflare Workers server adapter — the built worker ships its
  runtime shim, so even though it's a devDependency the vuln reaches
  production. Highest-priority fix.
- next 16.0.10 → 16.2.6: high-severity set (Server-Actions CSRF via
  null origin, middleware/proxy bypass, RSC cache poisoning,
  image-optimizer DoS). Several target the middleware GPC/AB surface.

Also bumped eslint-config-next to match (16.2.6) and ran npm audit fix
for transitive criticals (fast-xml-parser, serialize-javascript,
minimatch, etc.).

Result: 51 → 4 vulns. The remaining 4 are all moderate build-chain
transitives (postcss XSS via next, @opennextjs/aws) whose only
"fix" npm offers is a catastrophic downgrade — next→9.3.3 (destroys
the app) or @opennextjs→1.14.1 (reintroduces the SSRF just fixed).
They are build-time only (PostCSS never serves user content) with no
real runtime exposure and no forward fix available, so they are left
intentionally. Do NOT run `npm audit fix --force`.

Verified: lint + typecheck clean, 80 tests pass, `next build` +
`opennextjs-cloudflare build` both succeed (worker.js produced).

Note: 16.3.x is canary-only; 16.2.6 is the latest stable 16.x.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci: bump runner Node 20 → 22 (required by upgraded wrangler)

The @opennextjs/cloudflare 1.19.11 upgrade in this PR pulls a newer
transitive wrangler that requires Node.js >= 22. CI's setup-node was
pinned to node-version 20, so `wrangler dev` aborted on startup with
"Wrangler requires at least Node.js v22.0.0" — the wrangler-smoke job's
worker never came up and the readiness probe timed out.

Bumps node-version 20 → 22 in both ci.yml (Lint+Tests, wrangler-smoke)
and deploy.yml. This is distinct from the earlier Actions-runtime bump
(PR #38: checkout/setup-node action versions) — that was the action's
own Node runtime; this is the Node the action provisions for the
project toolchain.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…p) (#45)

Cuts the bloat findings from /m:audit --bloat — all scaffolding for
paths the architecture deliberately doesn't use. Zero behavior change.

- Remove trackConversion() + ConversionEvent (lib/ab-testing.ts): the
  function only console.log'd in dev; real conversion tracking is the
  variant written to Notion in the waitlist route (its own comment
  admitted this). Dropped the call site, import, and 4 tests.
- Remove getGpcFromCookie() (lib/gpc.ts): exported "for server
  components" but zero production callers — GPC is read client-side in
  AnalyticsGate/GpcNotice and request-side in middleware. Dropping it
  also removes the only next/headers cookies() import. Dropped 4 tests.
- Remove POSTHOG_ASSETS_HOST (lib/posthog/config.ts): exported, never
  imported. The CSP uses literal strings; init only sets api_host.
- Trim phase-2-in-comments (lib/posthog/events.ts) and restating
  JSDoc (lib/gpc.ts). Kept the @see INFRA refs and load-bearing
  compliance comments.

Perf finding (PERF-01): middleware now only clears being_gpc when the
cookie is actually present (request.cookies.has), instead of emitting a
needless clearing Set-Cookie on every no-GPC request — that Set-Cookie
on ~all traffic defeats shared/CDN caching of HTML responses. Updated
the middleware test accordingly (clears-when-present + does-not-emit-
when-absent).

Also: add /.open-next/ to .gitignore. The OpenNext Cloudflare build
output (27MB) was untracked-but-not-ignored, so a local
`opennextjs-cloudflare build` pollutes git status and makes `eslint`
glob 12k+ generated files. Pre-existing gap, fixed here since it bit
this very cleanup.

Net: ~70 LOC removed, 80 → 75 tests (removed 6 dead-path tests, added
1 middleware test). lint + typecheck clean, build + worker build OK.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MP2EZ MP2EZ merged commit f9423ab into main May 31, 2026
3 checks passed
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