← Back to journal

October 2026 security flaws: PHP, Node.js, npm and Shopify, what to check

In three weeks, PHP and Node.js shipped critical patches that were exploited in the wild, and Shopify stores saw their checkout hijacked through third-party apps. A concrete look at each flaw and the actions to take.

Three ecosystems that run a large share of the web were hit at the same time: PHP, which powers WordPress and most business websites, Node.js, which serves modern applications, and Shopify on the e-commerce side. In each case, exploitation started before or right after the patches were published. Here is what happened, and what you need to check on your site, whether you built it yourself or a provider hosts it for you.

Want to know where your site stands before reading on? Check it in one minute with the free tool: a grade from A to F, the missing protections and the action to take for each one.

PHP: php2shell, two critical flaws exploited before the announcement

On October 21, 2026, the PHP team shipped an emergency update for two flaws tracked as CVE-2026-109618 and CVE-2026-109619, nicknamed “php2shell”. Both score 9.2 out of 10. They let an attacker run code on the server without any account, through a single HTTP request.

  • The first corrupts memory while handling an out-of-memory condition.
  • The second exploits state kept between two requests (use-after-free).

Details leaked on social media on October 20, one day before the planned date. Amazon had already observed an exploitation attempt on October 17. On October 26, the US agency CISA added both flaws to its list of known exploited vulnerabilities.

Fixed versions: 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Branches 8.1 and earlier get no official release, only source patches to apply yourself or through your Linux distribution.

Who is affected: every installation that serves web requests, whether through PHP-FPM, mod_php, php-cgi, FrankenPHP or LiteSpeed. The risk is highest with mod_php, where the flaw triggers before your application even runs. A WordPress, PrestaShop or Laravel site is affected by definition.

To check your version and restart the processes after updating:

# Shows the PHP version on the command line
php -v

# On a Debian or Ubuntu server with PHP-FPM: a restart is mandatory,
# the package update does not touch processes already in memory
sudo systemctl restart php8.3-fpm
sudo systemctl reload nginx

One caution: versions 8.4.27 and 8.5.12 contain a regression that can crash applications using the SimpleXML extension. The fix is merged in the source but had not shipped as of October 26. Test before deploying to production.

If updating is impossible right away, PHP recommends two temporary settings, placed in a file the application cannot override:

; Neutralises CVE-2026-109618 (out-of-memory handling)
memory_limit = -1

; Neutralises CVE-2026-109619 (state kept between requests)
session.upload_progress.enabled = 0

Then restart every PHP process. These settings do not replace the update, they buy time.

If your site is on shared hosting, there is nothing to install yourself. But check the PHP version selected in your control panel: many hosts leave the choice to you, and a site left on 7.4 or 8.0 has no fixed version available at all.

Node.js: Node2Shell, a flaw in Brotli decompression

On the same October 21, Node.js shipped fixes for ten flaws, including CVE-2026-111497, nicknamed “Node2Shell”. It is an out-of-bounds write in the Brotli decoder bundled in the node:zlib module. A malformed Brotli stream is enough to crash the process, read its memory or run code.

Fixed versions: 22.23.4, 24.22.1 and 26.12.1. Lines 20, 23 and 25 are discontinued and will get no fix.

What makes this flaw concrete are the ordinary attack paths:

  • Express 5 and body-parser 2 decompress request bodies sent with the Content-Encoding: br header by default. Any visitor can therefore send the malicious stream to your API.
  • The built-in fetch() automatically decompresses Brotli responses. A compromised third-party server can target your application when it calls it.
  • Any code passing untrusted data to zlib.brotliDecompress().

A bare Node.js HTTP server, without a parsing middleware, does not decode incoming bodies and is not exposed through this path.

# Running version
node -v

# In a Dockerfile, pin a fixed version instead of a floating tag
# FROM node:22-alpine becomes:
# FROM node:22.23.4-alpine

If you cannot update immediately and your application does not need to receive compressed requests, disable decompression in body-parser:

// Compressed requests get a 415 response instead of being decoded
app.use(express.json({ inflate: false }));

Among the nine other fixes, two concern bypasses of TLS hostname verification, and another affects crypto.randomUUID() and crypto.randomInt(). For that last one, the advisory recommends rebuilding applications, not just updating the binary.

npm: worms spreading from package to package

The Node.js risk is not limited to the runtime. 2026 has seen a series of automated attacks on the npm registry, from the “Shai-Hulud” family. The largest so far, named CHAINDROP, started on August 4: the account of the maintainer of keyv, a library downloaded more than 600 million times a month, was compromised. Within two days, more than 400 packages were infected, with over a billion combined monthly downloads.

The method is the same in every wave:

  1. An infected package contains a preinstall script that runs during npm install, with no action on your part.
  2. The script collects the machine’s secrets: npm and GitHub tokens, SSH keys, cloud credentials, API keys for AI tools.
  3. With the stolen npm tokens, it republishes an infected version of every package the maintainer can access. That is what makes it self-propagating.

The measures that actually protect a project:

  • Block install scripts. npm 12 does it by default for preinstall. On earlier versions, add ignore-scripts=true to your .npmrc file and re-enable case by case.
  • Pin versions with a committed lockfile and install with npm ci, never npm install in production.
  • Wait before adopting a version. A version published a few days ago has had time to be reported if it is malicious. pnpm offers a minimum-age setting before a new version is considered.
  • Enable two-factor authentication on every npm and GitHub account, and refuse tokens that bypass it.

If a development machine installed a compromised package, treat all its secrets as stolen: revoke and regenerate.

Shopify: checkout hijacked through third-party apps

On October 10, a developer noticed that a Shopify store was redirecting its customers to a fake payment page at checkout. Shopify’s core was not compromised. The attack went through apps installed on the stores, mainly Hulk Product Options, then Swym Wishlist Plus and Selleasy on October 13.

The mechanism is instructive for anyone running a site with extensions:

  1. The app’s script loads normally from Shopify’s CDN.
  2. On load, it queries the app vendor’s API, which returns a block of custom code.
  3. That block, modified by the attackers, redirects the shopper to a fake checkout hosted on domains such as checkout-confirm.top.
  4. The fake page collects the card details, then sends the shopper to the real payment. The order goes through, the customer notices nothing.

Shopify removed the affected apps from its marketplace and, on October 20, rolled out a change: the store now asks the shopper to confirm before any redirect to an external site.

If you run a Shopify store, the test takes one minute:

  1. Open a private browsing window.
  2. Add an item to the cart and click Checkout.
  3. Check that the address shown stays on your domain or on shopify.com.

Then: uninstall apps you no longer use, change the Shopify password and those of app accounts, enable two-factor authentication, and review the integrations that have access to your store. This kind of Shopify intervention is handled in partnership with Huggii, contact me to learn more.

What these three cases have in common

In all three, the site itself was not the initial target. The entry point was a dependency: the language runtime, an installed library, a third-party app. A well-coded site that is never updated remains exposed.

The answer comes down to three habits: knowing your versions, updating them within the week following a critical patch, and limiting what an injected script can do through security headers. For that last point, I published a checking tool that reads your site’s headers and flags what is missing.

If your site runs on PHP or Node.js and you do not know who keeps it up to date, now is the time to find out. My maintenance offer covers exactly that. Let’s talk.