Skip to content

fix: NextJS security upgrade. - #951

Merged
jcmartinezdev merged 5 commits into
masterfrom
fix/next-security-upgrade
Sep 3, 2026
Merged

fix: NextJS security upgrade.#951
jcmartinezdev merged 5 commits into
masterfrom
fix/next-security-upgrade

Conversation

@jonathanp-okta

@jonathanp-okta jonathanp-okta commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

✏️ Changes

This upgrades next from 14.2.35 to 16.3.3 (with eslint-config-next and @next/mdx/@next/third-parties bumped in lockstep) to patch . The branch history shows the move was staged through 15.5.24 first (e3655c7) before continuing to 16.3.3 (48432f8, d9bccc9) — landing on the current major in one PR rather than opening a second migration shortly after. React stays on 18.3.1 throughout: 16.3.3 accepts ^18.2.0 || ^19.0.0 as a peer, so this is not a React 19 migration, and none of the direct dependencies (react-select, react-aria-components, react-markdown) pin react@^18 only — a future React 19 move stays unblocked.

Next 16 defaults to Turbopack, which broke @next/mdx: its loader registers as a plain top-level webpack rule with no App Router layer, so .mdx modules picked up node_modules' JSX runtime instead of Next's precompiled one and crashed in dev with ReactCurrentDispatcher of undefined. dev/build now pass --webpack explicitly, and next.config.mjs aliases react/jsx-runtime/react/jsx-dev-runtime to Next's compiled copies for the .mdx rule specifically (see the comment in next.config.mjs).

next lint was removed in Next 16.0, so lint now runs eslint . directly. Bumping eslint from ^8 to ^9 in the same PR meant ESLint's flat-config default would have silently ignored the legacy .eslintrc.jsoneslint.config.mjs replaces it as a direct re-export of eslint-config-next/core-web-vitals (confirmed to ship real flat-config arrays in v16, no FlatCompat shim needed), with two App Router-specific rule overrides carried over with their rationale in a comment. next-env.d.ts picked up a generated route-types reference (.next/dev/types/...) that Next writes on every dev/build and is committed so contributors don't get a dirty tree; tsconfig.json was updated to include that path and switched jsx to react-jsx / added target: ES2017 to match Next 16's expectations. next.config.mjs also sets agentRules: false so next dev stops writing AGENTS.md/CLAUDE.md into the tree.

Route/layout files were updated for Next 16's async params/searchParams/cookies()/headers() (all now return Promises) — PageProps/PageMetadataProps types, [language] layout and pages, not-found.tsx, and the language/theme cookie services. src/middleware.ts was renamed to src/proxy.ts (function renamed middlewareproxy) to match Next 16's rename of the convention. A handful of client components (footer, debugger-picker, mobile-header, the decoder/encoder input controls, card-toolbar-description-button) had useEffect-based "copy a prop/browser value into local state" patterns rewritten to sync during render instead (a new useClientValue hook covers the browser-only-value case); footer.component.tsx's react-select also gained an explicit instanceId so its generated DOM ids don't disagree between SSR and the client's first render.

preview.yaml, preview-community.yaml, and production.yaml also gained permissions: { contents: read, id-token: write } and two new steps before "Deploy on Vercel": a JFrog CLI setup that exchanges GitHub's OIDC token for short-lived Artifactory credentials (atko-cic provider), and a step that mints an .npmrc fragment into $RUNNER_TEMP from those credentials. The fragment is passed to vercel deploy as --build-env NPM_RC=..., which takes precedence over Vercel's project-level NPM_RC — the actual npm install for the deploy runs on Vercel's build machine, not the Actions runner, so that project-level value was the only credential in play and is what was producing npm error code E401. The credentials never touch the repo tree. The one substantive comment kept (# Artifactory credentials for the @a0 scope) is functional, not explanatory: Artifactory's response starts with @a0:registry=..., and the Vercel CLI reads a --build-env value starting with @ as a reference to a stored secret, so that line exists purely to keep the first character from being @.

Details worth a reviewer's attention:

  • React stays on 18.3.1. No dependency in this diff pins react@^18 only, so this doesn't block a later React 19 move.
  • --webpack is not cosmetic. Removing it would re-enable Turbopack and reintroduce the MDX JSX-runtime crash described above.
  • next-env.d.ts and the lockfile are committed on purpose — both are generated but need to be in the tree so CI and other contributors don't see a dirty diff after their first build.

🔮 Type of Change

Dependency/build-tooling patch plus the App Router API changes it forced. No product surface, no intentional runtime/behavior changes, no public API changes — the render-timing and react-select fixes are defensive corrections surfaced while QAing the upgrade, not new features.

  • Standard
  • Emergency
  • Significant

🔗 References

  • I added at least one link explaining why this change is needed.

📖 Documentation

No update needed — the only public-facing entry point (npm run lint) still means "lint the project"; its implementation changed but not its contract.

  • I reflected this change in the documentation, or explained why no update is needed.

🎯 Testing

  • npm run build (after rm -rf .next) — exit 0. ✓ Compiled successfully in 8.7s, ✓ Generating static pages using 9 workers (23/23) in 274ms, 23 App Router routes.
  • npm run lint (eslint .) — exit 0, zero findings.
  • npx vitest run — 11 files, 102 tests, all passing, 577ms.
  • npm run dev✓ Ready in 221ms; GET /200 (next.js: 7.4s, proxy.ts: 94ms, generate-params: 740ms, application-code: 347ms), no compile or console errors in the dev log.
  • npm auditnext no longer appears; 16 unrelated advisories remain (babel, vitest/vite, esbuild, nanoid, node-forge, svgo, yaml, etc.) and are out of scope here.

Gaps a reviewer should know about:

  • Playwright's browser suite (tests.yaml) was not re-run in this pass — CI will exercise it.

  • production.yaml only triggers on push to master/production (or schedule/workflow_dispatch), so its deploy path — including the new JFrog steps — is unverified by this PR directly; it runs for the first time on merge.

  • I could not find the advisory's patched-versions field in this repo/session — please confirm 16.3.3 is listed before merging.

  • I described how I tested these changes.

  • This change has test coverage, or I explained why it does not.

🚀 Deployment

Deployable at any time. 16.3.3 raises the Node floor to >=20.9.0 (up from 14.x's lower floor); tests.yaml/production.yaml already run Node 22, so this isn't a blocker, but it's worth confirming Vercel's project-level Node setting is ≥20.9 too — engines.node was deliberately left untouched (an open-ended range would let Vercel silently resolve to whatever the latest major is at deploy time). The atko-cic OIDC provider must already trust this repo, or the "Setup JFrog CLI" step fails outright — worth a quick check with JFrog admin access before merging if this hasn't been exercised yet.

  • This change can support multiple releases serving traffic at the same time.
  • This can be deployed at any time, or I listed the prerequisites.

🔥 Rollback

Revert this PR's commit(s) to return to next@14.2.35. Rollback restores a previously-working state (no new prod-only behavior was introduced ahead of this PR), so there's no residual-risk window — the deploy-workflow permissions/JFrog steps are additive and safe to leave in place even if the next bump itself were reverted.

  • I explained the rollback and recovery process.

@github-actions

Copy link
Copy Markdown

Preview URL https://next-jwt-ouc57bwdm-okta.vercel.app

@github-actions

Copy link
Copy Markdown

Preview URL https://next-jwt-ey912uwk2-okta.vercel.app

@github-actions

Copy link
Copy Markdown

Preview URL https://next-jwt-3u1zkjzwp-okta.vercel.app

@jonathanp-okta jonathanp-okta self-assigned this Aug 29, 2026
@jonathanp-okta jonathanp-okta added enhancement dependencies Pull requests that update a dependency file labels Aug 29, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Preview URL https://next-jwt-5utyyy7ri-okta.vercel.app

@jonathanp-okta
jonathanp-okta marked this pull request as ready for review September 1, 2026 06:20
Comment thread scripts/oidc-install.mjs
@jcmartinezdev
jcmartinezdev merged commit 0c75715 into master Sep 3, 2026
5 checks passed
@jcmartinezdev
jcmartinezdev deleted the fix/next-security-upgrade branch September 3, 2026 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants