---
title: "Everything That Broke On October 21st"
url: https://deallocatedobjects.com/posts/everything-that-broke-on-october-21st
author: Jake Marsh
published: 2026-10-22
updated: 2026-10-22
description: "Yesterday (Wednesday, October 21st) was one of the strangest days in security I can remember. By lunchtime TechCrunch was running a story titled \"The internet is having a very bad cybersecurity day\". None of these incidents are connected to each other. They just kept landing, one after another…"
---

# Everything That Broke On October 21st

By Jake Marsh, October 22, 2026. HTML: https://deallocatedobjects.com/posts/everything-that-broke-on-october-21st

Yesterday (Wednesday, October 21st) was one of the strangest days in security I can remember. By lunchtime TechCrunch was running a story titled ["The internet is having a very bad cybersecurity day"](https://techcrunch.com/2026/10/21/the-internet-is-having-a-very-bad-cybersecurity-day/). None of these incidents are connected to each other. They just kept landing, one after another, all day long.

Here's a rundown of what happened, roughly ordered by how much it should worry you, with as many technical details as I could dig up.

### PHP2Shell

The big one. PHP shipped emergency releases (**8.5.12**, **8.4.27**, **8.3.36** and **8.2.35**) at 14:00 UTC to fix two bugs that allow unauthenticated remote code execution. Both are rated CVSS v4 9.2.

**CVE-2026-109618** is out-of-memory handling interrupting PHP while internal request data is only partly initialized. Request cleanup then treats that half-built data as valid. **CVE-2026-109619** is request-owned state that survives after its memory is freed, so the next request on the same worker uses it before initialization resets it. A classic use-after-free.

The [php.net advisory](https://www.php.net/archive/2026.php) says every PHP install serving web requests is affected: PHP-FPM, `mod_php`, `php-cgi`, FrankenPHP and LiteSpeed. They consider `mod_php` the riskiest.

[Upwind traced](https://www.upwind.io/feed/initial-assessment-php2shell-two-critical-unpatched-php-rces-cve-2026-109618-cve-2026-109619) one confirmed path to `php_session_rfc1867_callback` in `ext/session/session.c`, the code that tracks upload progress on multipart POSTs. PHP caches a couple of `zval *` pointers while it counts bytes, then a session re-read destroys the hash table those pointers live in. The only precondition is `session.upload_progress.enabled=1`, which is the *default*. A stock `php.ini` is enough. Exploiting it needs a build-specific offset and wrong guesses crash the worker, so a burst of 502s from behind nginx is a decent sign someone's knocking.

The release was originally planned for today (the 22nd). Details and screenshots of an exploit tool leaked on the 20th, so PHP pulled it forward a day. Amazon's MadPot honeypots logged an exploitation attempt on **October 17th**, four days before anything was public, and nobody knows yet how that person got the details.

Calif found the bugs using OpenAI's GPT-5.6 Sol, and Wiz found them independently.

Then governments started pulling sites. The NSA said to take a system offline if you can't patch it right away. The UK took [32 government services offline](https://www.theregister.com/security/2026/10/22/php2shell-puts-dozens-of-uk-government-services-out-of-service/5304840) (and four more partially). The Netherlands, Finland, French local government sites, a Danish school platform and Australia's own cyber agency website went dark too. By that evening Pantheon alone had blocked over 60,000 suspicious requests, and Cloudflare was watching attackers mutate payloads to slip past its WAF rules.

If you can't upgrade yet, PHP lists stopgaps that shrink the attack surface (they're clear that only the update makes you safe). Put these in `php.ini` or your FPM pool config, since `ini_set()` and `.user.ini` apply too late:

```ini
session.upload_progress.enabled = 0
post_max_size = 8M         ; 32M if you need uploads
fatal_error_backtraces = 0 ; PHP 8.5 only
```

They also suggest `php_admin_value[memory_limit] = -1` in the FPM pool. Restart every worker afterwards. Also watch out for fake "PoC" repos on GitHub. JFrog has already found some carrying malware.

### LiteLLM 1.107.0

[LiteLLM](https://github.com/BerriAI/litellm), the Python proxy a lot of folks use to put a bunch of LLM providers behind one API, had a trojanized release up on PyPI, Docker Hub and GHCR for about two hours. It's the project's second compromise this year.

[StepSecurity's reconstruction](https://www.stepsecurity.io/blog/litellm-1-107-0-compromised-pypi-backdoored-wheels-credential-stealer) is wild. The attacker had stolen GitHub CLI OAuth tokens belonging to three BerriAI engineers. An org owner's token overrode branch protection at 10:08:34 UTC (five seconds after protection rejected the change) and rewrote the private release workflow to build from a lookalike repo, `Berri-AI/litellm`. Note the hyphen. A second engineer's token approved the production deploy, and a third one deleted the workflow run records.

Since the attacker changed the *trusted* workflow itself, all the hardening LiteLLM added after its March incident (Trusted Publishing, immutable tags, signed images) still applied to the bad build. The malicious packages shipped with valid provenance.

The wheels drop a 12-byte file called `cook.pth` that contains `import cook`. Python's `site` module executes import lines in `.pth` files on every interpreter start, so the stealer runs whenever Python starts on that machine. You never have to `import litellm` at all. Clever, and gross.

It grabs SSH and GPG keys, cloud credentials, cloud metadata endpoints, CI secrets, every process's `/proc/<pid>/environ`, browser passwords, and the config for AI coding tools like Claude Code, Cursor and Codex. If `DATABASE_URL` is set it also dumps LiteLLM's own tables, which are full of upstream provider keys. Everything gets encrypted (AES-256, with the key wrapped in RSA-4096) and POSTed to `http://www.litellm.dev/healthcheck`.

A second hook in `sitecustomize.py` forks a daemon that checks a GitHub repo under the account `letters9813` every hour for a hostname, then fetches whatever is at `/codepy` on that host and `exec()`s it. That GitHub account is gone now, but infected machines are still polling, and anyone who re-registers the name could run code on all of them.

Wiz estimates about 49,000 downloads. If you picked up 1.107.0 between 11:39 and 13:23 UTC (or pulled a floating Docker tag before 14:20), kill the loader process *before* you run `pip` again, because every Python start re-runs the stealer. Then rebuild the machine, pin `litellm==1.106.2`, and rotate every credential that box could reach.

BerriAI suspects the GitHub tokens leaked out of an internet-exposed internal LiteLLM deployment that logged response bodies, including responses where Claude Code had included the tokens. That part isn't confirmed. I use Claude Code all day, so this one hit close to home. Anything that shows up in an agent's output can end up sitting in somebody's logs.

### Railway

[Railway disclosed](https://blog.railway.com/p/security-disclosure-wednesday-october-21st) that someone got into the systems that store customer environment variables, and for some customers walked away with the decrypted values. Railway says it's part of a series of attacks on platform companies aimed at stealing keys for AI inference providers. They paused *all* deployments, invalidated API tokens and OAuth sessions, and warned upstream AI providers so they could revoke keys early. Researcher Taylor Monahan traced crypto theft back to at least two hours before the disclosure went up.

No root cause or customer count yet. If you're on Railway, rotate your secrets at the provider itself, since an old key keeps working until the provider revokes it. Their follow-up post specifically says to check your OpenRouter usage.

### ConnectWise And Storm-0940

[Microsoft published](https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/) its attribution for last week's ConnectWise Cloud Backup compromise: **Storm-0940**, a China-aligned group. The attacker took control of the identities of ConnectWise's multi-tenant Microsoft 365 apps and then signed in *as those apps* to customer tenants, riding the trust each tenant had already granted. Nobody had to type a password or approve an MFA prompt. Microsoft counted sign-in attempts against more than 2,250 tenants, peaking around 2,900 attempts per minute.

They automated it with ARTEX, an open-source multi-agent LLM pentest framework (Go backend, Next.js frontend) that works with any model. In some victims it went from first contact to privileged cloud access in under three hours, and in one tenant a ConnectWise app assigned *itself* Global Administrator.

Microsoft's advice is to disable the ConnectWise apps (search by app ID, display names can lie) and hold off on deleting them so you keep the evidence. Disabling them won't remove credentials the attacker already added to your other apps, so go check those too. ConnectWise started a phased restore yesterday.

### GitLab CVE-2026-110264

A CVSS 10.0. An integer overflow in the regex compiler lets an unauthenticated user run code on the server, and it affects every version back to **7.0**. That's 2014! It's [fixed in](https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-5-1-released/) 18.11.13, 19.0.10, 19.1.9, 19.2.9, 19.3.6, 19.4.3 and 19.5.1. There are no workarounds.

GitLab hasn't published the full path. [Secondary write-ups](https://lilting.ch/en/articles/gitlab-cve-2026-110264-org-mode-rce) point at Onigmo (Ruby's regex engine), reached by rendering an Org-mode `.org` file, which lines up with GitLab's own detection rules being named "Onigmo native worker crash" and "Org mode render error burst." This is a *different* bug from the CVSS 10 that GitLab fixed on October 12th. Patched last week? You need to patch again. No exploitation reported so far.

### eMudhra's Single-Byte CA Keys

This one technically broke a few days earlier, but the fallout peaked yesterday. eMudhra's stock fell about 20% after an exchange filing, and it was the #2 security story on Hacker News.

Eight eMudhra intermediate CAs (six for TLS, two for code signing), cross-signed by Sectigo's root, had P-384 private keys that were numbers between 0 and 255. [Scott Helme's write-up](https://scotthelme.co.uk/eight-bits-of-trust-emudhras-ca-keys-cracked-in-milliseconds/) lists all of them. One key is **4**. Getting a private key back from its public certificate takes at most 255 tries.

A bug in the April 2025 key ceremony script created a second, weak key pair on the HSM, and similar key names meant the wrong one got used for the CSR. These keys have effectively been public for about 17 months. Chrome found no TLS certs chaining to them in CT logs, and browsers blocked them within hours of the report. The real exposure is non-browser clients (`curl`, Python, Go, Java, package managers) that check neither CT nor revocation. Update your CA bundles (`ca-certificates`, `certifi`, Node, Homebrew) and rebuild your container images.

### Node.js

[Node.js 22.23.4, 24.22.1 and 26.12.1](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases) fix CVE-2026-111497, an out-of-bounds write in the Brotli decoder that allows remote code execution. OpenAI's Codex Security was one of the reporters. Anything that decompresses Brotli from an attacker (request bodies, fetched responses) is exposed, and Vercel pushed emergency firewall rules.

Also in that release: CVE-2026-106074, where `crypto.randomUUID()` and `randomInt()` had their entropy caches baked into user-land startup snapshots and single executable apps. Every process launched from one of those produced *the same* "random" values. Yikes. The release drops eMudhra from Node's CA bundle too.

### GMO Onamae.com Desktop Cloud

Over in Japan, GMO started shutting down *every* Onamae.com Desktop Cloud server at 04:00 JST after finding malware planted on customer machines. Up to 26,739 servers could be affected. The service is mostly Windows desktops running automated forex trading, and customers have reported unauthorized trades on their accounts. GMO hasn't published any malware details or IOCs yet.

### The Rest Of The Day

- CISA and the FBI put out a [joint advisory (AA26-293A)](https://www.bleepingcomputer.com/news/security/cisa-and-fbi-safepay-ransomware-has-hit-over-600-critical-infrastructure-organizations/) on SafePay ransomware, which has hit 600+ critical infrastructure organizations since August 2024.
- Palo Alto's GlobalProtect auth bypass (CVE-2026-0257) is [now a front door](https://www.helpnetsecurity.com/2026/10/21/ransomware-groups-exploit-palo-alto-globalprotect-cve-2026-0257/) for the Qilin, Inc and Settra ransomware groups. Patching doesn't kick out VPN sessions that already exist, so kill those after you patch.
- OVHcloud's CLI had release binaries v0.11.0 through v0.15.0 [swapped for a stealer](https://www.helpnetsecurity.com/2026/10/21/ovhcloud-cli-github-malware/) through a hijacked developer GitHub account. That happened on the 19th and was reported yesterday.
- State Bank of India confirmed 3,897 of its customers' records turned up in a leaked dataset.
- A [Miasma-variant npm worm](https://safedep.io/testmetest-npm-worm-miasma-variant/) got caught while still in testing. It runs from `binding.gyp`, so there's no install script to spot, and it wipes your home directory if you revoke the GitHub token it stole. Remove its persistence first, *then* rotate.
- The UK ICO reprimanded a Welsh public-sector IT provider whose 2024 ransomware breach started with a 12-year-old test account using the password `Password1`.

Holy cow. Go patch your stuff, y'all.
