All insights
Engineering··10 min read

Node.js, Next.js and Railway: Three Security Fixes Founders Need This Week

Three fixes founders need this week: a Node.js RCE patch, no Next.js 14 updates, and a Railway secret leak. Fixed versions and the Docker trap.

Node.js, Next.js and Railway: Three Security Fixes Founders Need This Week

PHP wasn't the only fire this week. If your product runs on Node.js or Next.js, three more things need your attention:

  • Node.js shipped fixes on 21 October for ten vulnerabilities. The worst one lets an attacker run code on your server.
  • Next.js patched two critical bugs and one high-severity bug on 14 October, and Next.js 14 gets no fix at all.
  • Railway, the cloud hosting platform, disclosed a breach of the system that stores customer environment variables.

We spent a full day patching ten client projects, most of them self-hosted Next.js apps running in Docker, and rotated every secret for one older client still on Railway. This article covers what each issue means, who is affected, the exact versions to install, and the mistakes we saw along the way, so you can hand it straight to whoever runs your servers.

1. Node.js: the 21 October security release

The Node.js project fixed ten vulnerabilities across every supported release line. Four are rated high.

The most serious is CVE-2026-111497, an out-of-bounds write in the Brotli decoder that can lead to remote code execution. Brotli is a compression format websites use to shrink data before sending it, much like a zip file. Node decompresses it automatically, and a specially crafted compressed response can corrupt memory on your server.

This matters most for apps that fetch data from outside sites: scrapers, webhook consumers, link previews, RSS readers, AI agents that browse. Node's built-in fetch decompresses Brotli responses on its own, so the attacker only needs your server to request a page they control.

Two other high-severity fixes:

  • dns.resolve truncates hostnames that contain a NUL character, which can send traffic to the wrong place.
  • TLS hostname checks can be bypassed with an IP address written in fullwidth digits (CVE-2026-105483).

Fixed versions

Release lineInstall this or later
Node.js 2626.12.1
Node.js 24 (LTS)24.22.1
Node.js 22 (LTS)22.23.4

Node.js 20 and older get no fix. Node 20 reached end of life in April 2026, and the Node.js team notes that unsupported versions may also be affected. If anything you run is still on 20, this is the moment to move to 22 or 24.

2. The Docker trap: your server's Node is not your app's Node

This is where most teams get caught. If your app runs in Docker, which covers Coolify, Railway, Render, Fly.io, Kubernetes and most VPS setups, every container carries its own copy of Node.js. Updating Node on the host machine changes nothing inside the containers. Restarting them changes nothing either, because they come back from the same old image.

The fix lives in the image: change the Node version in the Dockerfile, rebuild, and redeploy.

What we found across ten projects

None of these apps had a security problem in its own code. Every issue was in how the image got built:

  • Auto-builders chose the version. Apps built by a buildpack (Nixpacks, in our case) got whatever Node the builder decided on. One was on Node 22.11.0 and another on 20.18.1, and nobody had picked either. One build broke outright, because the newer Prisma needs Node 22.12 or later.
  • Browser images bundle their own Node. Scraper apps built on the official Playwright image ran the Node that shipped with that image, frozen at its release date.
  • Floating tags hide the real version. A Dockerfile that says node:22 gives you whatever that tag pointed to on the day of the last build, not today's patched release.

How to check every container

Run this on the server. It prints the Node version inside each running container:

for c in $(docker ps -q); do
  echo "$(docker inspect -f '{{.Name}}' $c): $(docker exec $c node -v 2>/dev/null || echo no-node)"
done

Anything older than the fixed versions above needs a rebuild.

Pin the exact version

We moved every app to its own Dockerfile with the exact version pinned, for example FROM node:24.22.1-bookworm-slim. For images that ship their own Node, such as Playwright, we install the official Node binary on top, verify its SHA-256 checksum against nodejs.org, and fail the build if node -v does not match. You always know what is running, and the next patch is a one-line change.

3. Next.js: the 14 October security update

A week before the Node release, Next.js patched three vulnerabilities:

IssueSeverityWho should worry
Remote code execution in SVG image processingCriticalSelf-hosted apps that use next/image, especially with user-uploaded or remote images
Remote code execution in use cache (Cache Components)CriticalApps using use cache functions that return typed arrays, which is uncommon
Denial of service in App Router Server ActionsHighAny App Router app that uses Server Actions

The image bug matters most if you self-host. On Vercel or Netlify, image optimization runs on the platform. On your own VPS, it runs on your server.

Fixed versions

  • Next.js 15.5 → 15.5.28
  • Next.js 16.4 → 16.4.1
  • If you can't upgrade today, make sure the sharp package Next.js uses is 0.35.5 or newer. That closes the image path while you plan the upgrade.

If you're still on Next.js 14

Next.js 14 gets no patch. Two of our apps were on 14.2.35, so we upgraded them straight to 16.4.1. The changes that took real work:

  • cookies(), headers(), params and searchParams are now async. The official codemod handles most of it, and anything wrapping a Supabase or auth server client needs an await.
  • middleware.ts is renamed to proxy.ts.
  • Server-only packages such as Playwright move to serverExternalPackages in next.config.js, now that Turbopack is the default build.
  • next lint is gone. Use ESLint directly with a flat config.

Neither upgrade needed changes to business logic or UI. Do it on a branch, run npm run build, and test sign-in, protected routes and anything that takes route parameters before you merge.

Next.js now publishes security fixes every month and has released 41 advisories in 2026 so far, 32 of them since May. Falling a few minor versions behind now means falling behind on security too.

4. Railway: customer secrets exposed

On the morning of 21 October, Railway detected unusual activity in the system that stores customer environment variables. The attacker accessed encrypted variables and decrypted some of them, including API keys, database credentials and private registry credentials. Railway paused all deployments and told customers to rotate their secrets immediately.

Railway described it as part of a wider series of attacks on platform companies, aimed at stealing API keys for AI model providers.

If you host anything on Railway, or ever did, assume every secret stored there is known to someone else. Rotate them in this order:

  1. Database passwords and connection strings. These give direct access to your data.
  2. Payment keys (Stripe and similar). Roll them, then check for unexpected charges, refunds or webhooks.
  3. AI provider keys (OpenAI, Anthropic and others). These are the main target, and a stolen key can run up a large bill fast. Set usage limits while you're in the dashboard.
  4. Auth secrets (AUTH_SECRET, JWT_SECRET, OAuth client secrets). Rotating these signs everyone out, which is the point.
  5. Email, SMS and storage keys (Resend, Twilio, S3 and similar).
  6. Any key that is shared with an app hosted elsewhere. A leaked key is leaked everywhere it's used.

One of our older client apps was still hosted on Railway. We didn't wait to find out whether its keys were among the decrypted ones. We rotated every secret the same day, working through the order above, and redeployed with fresh credentials. When a platform says secrets may be exposed, treat them as exposed: rotating a key that turned out to be safe costs an hour, and a stolen one can cost far more.

If you never used Railway, nothing here applies to you. Note that Nixpacks, the build tool many self-hosted platforms such as Coolify use, was created by Railway but runs on your own server. Using it does not put your secrets on Railway.

Patch checklist for founders

Hand this to your developer or agency. Count an item as done only when you have evidence, such as a version printed from inside the live container or a merged commit, not just someone saying "we're patched."

Node.js

  • List every app and worker that runs Node, including cron jobs, queues and forgotten side projects
  • Run node -v inside each running container, not on the host
  • Pin the exact fixed version in each Dockerfile (24.22.1, 22.23.4 or 26.12.1)
  • Rebuild without cache and redeploy
  • Re-run node -v in the live container to confirm
  • Move anything on Node 20 or older to 22 or 24

Next.js

  • Run npm ls next and confirm 15.5.28 or 16.4.1
  • Upgrade anything on Next.js 14 on a branch, then build and test before merging
  • On self-hosted apps, confirm sharp is 0.35.5 or newer

Railway

  • Confirm whether any app or key ever lived on Railway
  • If yes, rotate every secret and set usage limits on AI provider keys

After deploying

  • Test sign-in, payments, uploads and background jobs on the live site
  • Check logs for build or runtime errors for 24 hours

FAQ

We're on Vercel. Do we need to do anything?

For Node.js, set your project's Node version to 22.x or 24.x in the Vercel settings, and redeploy so new builds pick up the patched runtime. For Next.js, you still need to upgrade the next package itself. Vercel handles image optimization on its platform, which lowers the image-bug risk but does not remove the other two. Our own site runs on Vercel: we set Node.js to 24.x and moved Next.js from 15.5.12 to 15.5.28 in a single commit.

We updated Node on the server and restarted. Why are we still exposed?

Because your app doesn't use the server's Node if it runs in Docker. Each container has its own. Check with node -v inside the container, then rebuild the image.

Should I use node:24 or pin node:24.22.1?

Pin the exact version. A floating tag only updates when you rebuild, and you can't tell which patch is running without checking. Pinning makes every security update a visible, reviewable one-line change. Tools like Dependabot can open those pull requests for you automatically.

Is upgrading from Next.js 14 to 16 risky?

It's a real migration, but a predictable one. On our two apps it took a few hours each, with no changes to business logic. Do it on a branch, let the codemods do the bulk, and test sign-in and dynamic routes before you merge.

Does the Railway breach affect self-hosted apps?

Only if the same keys were also used on Railway. Secrets stored in Coolify or on your own server were not part of this breach.

Not sure what's actually running in production?

We check the Node.js and Next.js versions inside your live containers, pin them, and upgrade what needs upgrading, with a rollback plan. If your app was AI-built or inherited from another team, start with a free Finish Line Scan.

Get a free scan