The Day in Order
Put the events of October 20 and 21 in order and a plain story appears: a bug in software most of the web runs on leaked two days early, attackers were already probing for it, and every organization on a supported version had a one-line fix while everyone else had to pull the plug. The press has started calling the month Black October. All times are UTC.
| When | What happened |
|---|---|
| Oct 17 | Amazon's honeypots record the first attempt to exploit the PHP flaws, four days before anyone outside the embargo was supposed to know they existed. The same day, a researcher reports that the private keys behind eight eMudhra certificate-authority certificates are weak enough to recover. Chrome blocks them within two hours. |
| Oct 20, 13:58 | Monitoring pages an on-call engineer at Railway, a cloud platform developers deploy applications to. By mid-afternoon the team is fighting an intruder escalating privileges inside its build infrastructure. |
| Oct 20, about 15:00 | The two PHP CVE identifiers surface online. The PHP team announces an emergency release and moves it a day earlier, to October 21 at 14:00. That evening a proof-of-concept video is posted by mistake. |
| Oct 21, from 02:00 | Working exploit attempts from several actors begin hitting Amazon's sensors. At 03:02, Cloudflare switches on blocking rules for every customer, including free plans, eleven hours before the patch ships. |
| Oct 21, 07:41 | A container vendor publishes images containing the fix ahead of the embargo, handing anyone who wanted it the patch to reverse-engineer. |
| Oct 21, 11:39 to 13:23 | A poisoned release of LiteLLM, a popular Python library for calling AI models, sits on PyPI for under two hours, stealing credentials from every machine that installs it. |
| Oct 21, 14:00 | PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35 ship. CISA, the NSA, and the UK's NCSC publish alerts. Banks, ministries, and companies in Japan, and government sites in the Netherlands, Finland, France, Denmark, and Canada, go offline rather than wait. |
| Oct 21 | Node.js fixes ten vulnerabilities, including a remote code execution flaw in its Brotli decoder. GitLab fixes a maximum-severity flaw present in every self-managed release since 2014. |
| Oct 21, 20:19 to 22:10 | Railway publishes its disclosure: encrypted customer secrets were queried, and some were decrypted. Every user is told to rotate every environment variable and API key. |
| Oct 22, 03:32 | Railway confirms the attacker no longer has access, and publishes a preliminary report later that day. |
| Oct 23 | PHP posts an advisory for a related, narrower issue (CVE-2026-115560). CISA revises its alert with detection rules. |
PHP2Shell, Explained
PHP2Shell is the name given to two bugs, CVE-2026-109618 and CVE-2026-109619, in the PHP engine itself. Not in WordPress, not in a plugin, in the language runtime underneath them. Both let an attacker who has no account send a crafted web request and run their own code on the server. The PHP team rated both 9.2 out of 10 on CVSS v4.0. On Apache with mod_php, which the PHP team considers the highest-risk setup, the attack lands before any application code runs, so an application's own login screen cannot stop it. Wiz, one of the firms that found the bugs, demonstrated remote code execution against stock WordPress, Drupal, and Joomla and noted that "even a simple 'Hello World' application running on an affected PHP version can be vulnerable."
The scale is what made governments react. W3Techs counts PHP on 69.2% of websites whose server-side language it can identify. Nearly every version from PHP 5.4, released in 2012, through 8.5 was affected by at least one of the two, which means the bugs had sat in the code for roughly fourteen years. The PHP Foundation's own account is unusually candid: a core developer noticed signs of the memory bug during an outside audit in 2024, but with no working exploit and no consensus on a fix that would not break things, the decision process "caused work on a fix to stall and restart repeatedly over months." The Foundation calls the delay "a structural failure." In 2026, researchers at Calif and OpenAI, through OpenAI's Patch the Planet program, and separately at Wiz, which used AI-assisted tooling, turned that old suspicion into a working exploit and reported it in August.
The disclosure then went wrong in the way disclosures now do. The table above shows the leak, the early release, and the pre-embargo images. Amazon's threat intelligence team, which found exploit attempts in its honeypot data from October 17, drew the conclusion that matters here: "An embargo protects defenders only until someone else finds the same bug," and "defenders should not assume the public disclosure date is the earliest date of exploitation."
From PHP's release announcement: "There are no complete mitigations, updating is the only safe choice." Configuration changes reduce exposure to specific paths. Only the update closes them all.
If your server ran PHP 8.2, 8.3, 8.4, or 8.5, the fix was a package update. If it ran PHP 8.1 or older, the PHP project had no packaged release for you: those branches left support before the bug was found. The team published minimal source patches for 7.4, 8.0, and 8.1 as a courtesy, and some Linux distributions backported fixes, but CISA's advice for anyone who could not update, or who "continue to use PHP 8.1 or earlier unsupported versions," was to "take PHP-based systems offline until they can be patched or updated." That is the whole argument for staying on supported software, in one sentence from the government.
A web application firewall helped but did not solve it. Cloudflare blocked known exploit patterns from 03:02 on October 21, then watched attackers "mutating the attack payload to try to bypass our protections," and told customers to patch anyway. CISA's alert, last revised October 23, says the agency has "not observed successful exploitation of these vulnerabilities in the wild." That is good news, and it is not the same as no one being compromised. The shutdowns in Europe and Japan were precautions, not confirmed breaches. Finland's state IT center, which took the government's public web services offline, said it had not identified any attempt to exploit the flaws and that the outage was not a data breach, and the Japanese Bankers Association reported no impact on the interbank settlement network.
The Railway Breach
Railway is a cloud platform, not a rail company. Developers push code to it and it runs the application for them, in the same family as Heroku or Vercel. Applications on Railway keep their secrets, meaning database passwords, API keys for payment and AI providers, and credentials for private container registries, in environment variables that Railway stores encrypted. On October 21 Railway's disclosure said that "an unauthorized third party may have accessed encrypted environment variables and, for some of them, obtained the decrypted contents," and told every customer to "immediately roll all environment variables, including any API keys."
Railway's preliminary report, published the next day, describes an attacker who was inside from 13:58 on October 20 until 03:32 on October 22. The path was a chain of internal hops: a privilege escalation in the build infrastructure, then credentials for the CI environment, then the ability to decrypt artifacts that held more API access, then a query against the encrypted secrets store. Railway says the intruder's own payload logs showed exactly which API key names they were hunting for, and that the campaign "was attempting to obtain AI provider API keys to perform distillation attacks," that is, to copy a commercial AI model by querying it at scale on someone else's bill. Railway puts the exposure at "at most 1.85% of all workspaces," about 100,000, and says user accounts were not accessed and running deployments stayed online. It has not yet ruled out access to source code. The incident appears to be unrelated to PHP2Shell; the two simply landed on the same day.
The Railway lesson is about secrets rather than patches. A credential is only as safe as every system that can read it, and a stolen key works until someone revokes it. Railway's response was the right one, even though it was disruptive: pause deployments, tell everyone to rotate, and hand upstream providers the full list of keys so they could revoke them proactively. For a small business, the same logic applies to the hosting account, the payment processor key, and the database password that has been the same since launch.
The Rest of the Day
Three other fixes shipped on October 21, and one certificate problem from the weekend before was still unwinding. Each one is an argument for the same habit.
- LiteLLM supply-chain attack. Version 1.107.0 of LiteLLM on PyPI, and the matching Docker images, carried malware that ran every time Python started on the machine, even if the program never used LiteLLM. Wiz's analysis found it collecting browser passwords and cookies, AWS, Google Cloud, and Azure credentials, SSH keys, and API keys for AI providers. It was live from 11:39 to 13:23. LiteLLM's account of the attack chain traces it to a master key committed to a public repository on May 27 and never revoked. On October 10 the attacker used that key to obtain a maintainer's GitHub token, took two more through CI workflows, and on October 21 pointed the release pipeline at a lookalike repository. The clean version is 1.106.2; anyone who installed 1.107.0 is told to rebuild the machine and rotate everything it could reach.
- Node.js security release. Node.js 22.23.4, 24.22.1, and 26.12.1 fix ten vulnerabilities, the worst a Brotli decoder bug (CVE-2026-111497) where malformed compressed data can corrupt memory and run code. The release notes include a line every operator should memorize: "End-of-Life versions are always affected when a security release occurs." Node 20 and earlier got nothing.
- GitLab, CVSS 10.0. CVE-2026-110264 is an integer overflow in the regular-expression engine GitLab bundles with Ruby. It lets an unauthenticated attacker run code on a self-managed server, affects every version back to 7.0 from 2014, and has no workaround. The fix is in 19.5.1, 19.4.3, and 19.3.6, with backports down to 18.11.13. Instances that applied a similar fix nine days earlier were vulnerable again and had to update a second time.
- eMudhra certificate keys. The private keys for eight intermediate certificate-authority certificates were generated with so little randomness that outsiders recovered them. Google received the report at 18:05 on October 17 and had Chrome blocking the keys by 19:45. Chrome users were covered within two hours of the report. The long tail is every server, script, and appliance that carries its own list of trusted authorities and has not been updated. The Node.js release above included that update.
For context, Microsoft's regular Patch Tuesday a week earlier fixed 1,411 flaws, a record, including one already being exploited. The volume is not going down.
Why Software Updates Matter More Than They Used To
For most of the last decade the standard advice was that attackers get in through people: a phished password, a reused credential. That changed this year. Verizon's 2026 Data Breach Investigations Report found that 31% of breaches now start with the exploitation of a software vulnerability, "beating stolen passwords as the top way attackers get in." The year before it was 20%. The same report found organizations take a median of 43 days to fix a vulnerability that is already being exploited, up from 32, and fully fix only 26% of them.
Forty-three days is a long time when the other side moves in hours. PHP2Shell was probed before disclosure and had proof-of-concept exploits circulating within hours of the patch. Amazon's security team now tells its customers to "measure patch and mitigation timelines in hours. A 7-day or 30-day SLA assumes a delay that no longer exists," and names the reason: AI-assisted analysis "makes it cheaper to turn a patch diff or advisory into a working exploit." The same tools that found PHP2Shell will find the next one, on both sides.
An update you can apply in an hour is the cheapest security control you will ever buy. An update you cannot apply, because the software left support, is the most expensive.
End of life is the trap inside this story. Every product above drew the same line: PHP 8.1 and older, Node 20 and older, GitLab builds outside the support window. Past that line the vendor ships no fix. You depend on a distribution or vendor backport, if one exists, and when none does the only safe option is the one CISA gave, which is to turn the system off. The dates are published years ahead. PHP 8.2 ends on December 31, 2026. .NET 8 and .NET 9 end support on November 10, 2026. If a system you depend on is near one of those dates, the next PHP2Shell is the day you find out what unsupported means.
Private Services Are Not Exempt
The usual reason an internal system goes unpatched is that it is "not on the internet." October 21 undercut that in three ways.
First, you may not know where the software is. CISA's alert notes that "PHP is often a component of other software and prevalence may not be directly observable." The UK's NCSC told organizations to find every PHP install, "do not limit discovery to outdated PHP versions," and to update "internet-facing systems first and then internal systems." Internal, not never. PHP lives in network appliances, printer admin pages, monitoring dashboards, intranet wikis, and the control panel your host gave you.
Second, the first foothold is rarely the target. Railway's attacker started in build infrastructure and walked, hop by hop, through internal systems to the secrets store. LiteLLM's attacker started from a key that had been committed to a public repository five months earlier and never revoked. Once an attacker has one phished laptop or one stolen VPN password, your internal network is the internet for them, and an unpatched internal server is simply the second step.
Third, internal systems age worse. They have no uptime dashboard, no customer complaining, often no owner. They run the PHP version the vendor shipped, on the Windows version that was current at install, with logs that roll over every week. That is exactly the profile of system that gets found during an incident rather than during an update window.
Patch Management for a Small Team
None of this requires an enterprise security department. It requires a short list, kept current, and someone whose job it is to act on it.
- Keep an inventory. Every server, application, runtime, database, appliance, and hosted service, with its version and what it embeds. On October 21 the organizations that patched in an hour were the ones that could answer "where do we run PHP?" without a meeting.
- Stay on supported versions, and put the end-of-support dates on a calendar. Plan the upgrade a year out, not the week the vendor stops shipping fixes.
- Subscribe to the sources. Your vendors' security announcement lists and CISA's Known Exploited Vulnerabilities catalog, which lists flaws confirmed to be used in attacks. You should hear about the next one from the vendor, not from a customer.
- Set two speeds. Routine updates on a schedule, monthly or faster. Critical flaws in anything that faces a network within hours, and a rehearsed way to take a system offline if you cannot. Under a directive issued in June, CISA now gives federal agencies three calendar days for the most dangerous class of flaw and requires them to check whether the system was already compromised. A small team can be faster, because it has less to coordinate.
- Make updates safe to apply. A staging copy, a backup you have tested by restoring it, and a known way to roll back. Teams that are afraid to patch do not patch.
- Reduce what is reachable. Nothing on the public internet that does not need to be there. Databases on a private network only, which Railway listed first in its own recommendations. A web application firewall as a layer, never as the fix.
- Treat secrets as inventory too. Know where every API key, password, and certificate lives and what it can do, so you can rotate all of them in an afternoon. Give each one the least access it needs. Never let a long-lived key land in a log.
- Ship logs somewhere else. CISA's guidance for the Citrix incidents this fall warns that "local logs may rotate quickly and overwrite forensic artifacts." If the only copy of the log is on the compromised box, you will never know what happened.
- Give it an owner. Patching that is everyone's job is nobody's job. The owner can be on staff or under a care plan.
If You Think a System Was Hacked or Exposed
Maybe you ran an old PHP version on a public site. Maybe you had keys on Railway, or a developer installed LiteLLM that morning. The order below is the one incident responders use, and the sequence matters: contain and preserve, then patch, then revoke, then hunt, then rebuild and issue new credentials.
- 1Start the clock earlier than the headline
Amazon's advice for PHP2Shell was to "start investigations from the earliest known exploitation, not from the disclosure date," which means October 17, not October 21. For any incident, assume the attacker had days before you heard about it.
- 2Preserve evidence before you change anything
Copy logs off the machine, take a disk or VM snapshot, and note the time. CISA's Citrix guidance is blunt that "updates may reduce forensic visibility," and the NCSC asks you to "assess the system for any evidence of compromise prior to your upgrade." Spend minutes on this, not days, and disconnect the system from the network while you do it. Isolation costs nothing you cannot restore, and it stops an attacker who is still inside from using the system while you work.
- 3Patch, or take it offline
Update to the fixed version. If no fixed version exists for what you run, the system stays offline until it is rebuilt on a supported one.
- 4Revoke every credential the system could reach
Not just the ones you think were taken, and do it from a machine you trust, not the one under investigation. Administrator and service-account passwords, including domain accounts if the server was joined to one. Database passwords. API keys for every third-party service. Cloud access keys and roles. SSH keys. Source-control and CI tokens, including GitHub or GitLab personal access tokens, OAuth app grants, and deploy keys. Container registry credentials. TLS certificates and the private keys behind them. Signing keys for sessions and tokens, and then invalidate active sessions and refresh tokens, because a new key alone does not end them. On a developer machine, add browser-saved passwords and every logged-in session. Revoke at the provider first, so the old value is dead before anyone can use it, and issue the replacements only to a system you have rebuilt or verified clean, never back into the one you are still investigating. Then turn on multi-factor authentication where it was missing. CISA's recovery steps for the Ivanti VPN flaw this month give the same list: reset "all accounts, including domain, administrator, and local accounts," revoke and reissue certificates, and reset API keys.
- 5Hunt for what was left behind
Attackers who get code execution leave a way back in. Look for web shells: new or recently modified PHP files, especially in upload and cache folders. Look for web server worker processes that launched a shell or downloaded tools, which CISA lists as the signature of a PHP2Shell compromise. Check for new administrator accounts, new scheduled tasks or cron jobs, changed startup scripts, and outbound connections you do not recognize. Then check the audit logs of everything the stolen credentials could reach: cloud account activity from unfamiliar addresses, GitHub audit logs and installed applications, registry pull and push logs. Wiz's indicators for PHP2Shell on the server itself are memory-limit errors followed by repeated 500 responses, oversized or malformed session cookies, and PHP workers restarting more than usual.
- 6Rebuild rather than clean
Once code has run as your web server, you cannot prove you found everything. Restore from a backup that predates the earliest possible compromise, or rebuild the server from a clean image and your source repository, apply the patch, and only then give it the new credentials from step 4. Railway rebuilt its infrastructure tooling "from validated source" and rolled every key a second time after confirming the intruder was out. The same principle holds for a single server.
- 7Tell people, and write it down
Customers whose data could have been reached, the providers whose keys you rotated, your insurer, and any regulator your industry answers to, within the deadlines that apply to you. Then write a one-page timeline while it is fresh. Every item on it that reads "we did not know we ran this" or "the version was out of support" becomes the next entry on the practices list above.
CVE, CVSS, and KEV in Plain Words
Three terms and one date do most of the work in security advisories, and the alerts are easier to act on once they are clear.
Common Vulnerabilities and Exposures. One identifier for one publicly known flaw, such as CVE-2026-109618, so that a vendor advisory, a scanner, and a news article all point at the same thing. The number says nothing about severity.
Common Vulnerability Scoring System. A 0 to 10 severity score. Scores of 9 and above are reserved for the worst cases, typically a flaw an attacker can exploit over the network with no account. The current version is 4.0; older 3.1 scores for the same bug can differ, which is why you sometimes see two numbers.
CISA's Known Exploited Vulnerabilities catalog. Flaws confirmed to be used in real attacks, with a deadline for federal agencies to fix them. It is a free watchlist for anyone. PHP2Shell was not on it as of this writing, because confirmed exploitation had not been documented; absence from the list is not safety.
The date after which a vendor ships no more security fixes for a version. From that day, any fix for a new flaw has to come from someone other than the vendor, if it comes at all.
- PHP: Security advisory, critical remote code execution vulnerabilities, update now (October 21, 2026; fixed versions, affected installations, end-of-life branches, mitigations)
- The PHP Foundation: Today's PHP security release and how we're strengthening PHP security (October 21, 2026; discovery, the 2024 history, the leak and early release)
- CISA: Critical vulnerabilities in PHP require immediate patching (October 21, revised October 23, 2026)
- UK National Cyber Security Centre: Critical security issue affecting PHP (October 21, 2026)
- AWS Security Blog: Amazon Threat Intelligence identifies PHP2Shell exploitation prior to public disclosure (October 21, 2026)
- Cloudflare: Cloudflare deploys protections against php2shell vulnerability (October 21, updated October 23, 2026)
- Wiz Research: PHP2Shell (October 21, 2026; demonstrated targets, indicators)
- W3Techs: Usage statistics of PHP for websites (read October 26, 2026)
- Jiji Press via nippon.com: Japan banks, other firms take precautionary measures over PHP flaw (October 22, 2026)
- Reuters via The Korea Times: Govts, companies take websites offline over PHP vulnerabilities (October 23, 2026; Finland, the Netherlands, France, and Canada) and Engadget: Government websites in the EU and Canada taken offline over PHP vulnerability (October 21, 2026; Denmark)
- Anadolu Agency: Japan suspends several websites over critical PHP security vulnerabilities (October 21, 2026; the Health, Labor and Welfare Ministry)
- CISA: Binding Operational Directive 26-04, Prioritizing Security Updates Based on Risk (June 10, 2026)
- Railway: Security disclosure, Wednesday October 21st and Preliminary report: Oct 21st security incident (October 21 and 22, 2026)
- TechCrunch: Developer platform Railway urges all users to revoke secret keys after cyberattack (October 22, 2026; the breach is unrelated to the PHP flaws)
- GitGuardian: New Railway incident, treat every environment variable as exposed (October 22, 2026; rotation order)
- LiteLLM: Oct 21, 2026 release v1.107.0 compromised (October 21, 2026) and the attack chain (October 23, 2026); Wiz: LiteLLM compromised, steals credentials (October 21, 2026)
- Node.js: Wednesday, October 21, 2026 security releases
- The Hacker News: Critical GitLab flaw (CVSS 10.0) (October 21, 2026)
- Google Security Blog: Protecting Chrome and Android users from compromised eMudhra intermediate CA certificates (October 20, 2026)
- BleepingComputer: Microsoft October 2026 Patch Tuesday fixes 1,411 flaws, 3 zero-days (October 13, 2026)
- Verizon: 2026 Data Breach Investigations Report (31% of breaches start with vulnerability exploitation) and watchTowr's summary (prior-year 20%, 43-day median, 26% fully remediated)
- CISA: Critical zero-day vulnerabilities exploited in Citrix NetScaler ADC and Gateway (September 27, revised October 9, 2026; forensics before patching, log retention) and CISA urges patching newly exploited vulnerability in Ivanti Connect Secure (October 13, 2026; recovery and credential reset steps)
- CISA: Known Exploited Vulnerabilities catalog
Keep Reading
Care Plans
Security patches and dependency updates on a set schedule, monitoring, and backups tested by restoring them.
See the service Service.NET Upgrades
.NET 8 and 9 end support on November 10, 2026. What that means and how to plan the move.
See the service ServiceSoftware Rescue & Takeover
When nobody knows what version an inherited system runs, start with a Production-Readiness Review.
See the service GuideTaking over an undocumented codebase
Secure access and credentials first, then source control, then a map of what runs where.
Read the guideNot sure what you run, or when it was last updated?
We reply within one business day, and the first conversation is always free. Call (859) 429-2846 or send a note.
Start the Conversation →