When Foundations Fail: Lessons in Modern Incident Response 

Technical Reviewer
Updated: October 22nd, 2026
18 mins read
When Foundations Fail: Lessons in modern incident response

A day-two guide for security leaders: what to do now, today and this week, which controls would have broken each attack, and where the evidence is still thin.

Last updated: October 22, 2026. We update this post as vendors publish new details. The update log is at the bottom.

Most security and modern incident response programs ask one question: what do we need to patch? On October 21, 2026, patching covered three of the eight incidents in the headlines. For the other five, the damage was already done or sat somewhere no patch reaches.

In this blog, we cover what happened in each incident, the key action steps, which controls would have broken the attack, where those controls fall short, and what information is still awaited.

What to do, in order

Here’s how we’d sequence it. 

  • PHP2Shell leads because it exposes the most systems, and the honest first step is finding out how many PHP runtimes you actually have. 
  • LiteLLM is second for anyone who ran it, because stolen credentials don’t wait for your change window. 
  • Railway is real work, but it’s rotation and containment, so it sits behind the patch-now items. 

If you started yesterday, the last column is a quick way to see whether you’re actually done.

WhenIncidentDo thisDone when
NowPHP2ShellInventory every PHP runtime. Upgrade to 8.2.35, 8.3.36, 8.4.27 or 8.5.12, restart workers, isolate end-of-life hostsThe running version, not the installed one, is verified on every host
NowLiteLLMSearch lockfiles, CI logs and image manifests for litellm 1.107.0. If a host ran it, isolate it, rebuild, and rotate every secret it could reachNo host ran it, or every reachable secret is rotated and provider usage is reviewed
TodayGitLabUpgrade self-managed instances to your branch’s fixed release, even if you patched on October 12. Turn on GitLab’s two detection rules and get the login page off the open internetRunning version confirmed; CI tokens, deploy keys and runners reviewed if the instance was exposed
TodayNode.jsUpgrade to v22.23.4, v24.22.1 or v26.12.1 and rebuild images. Start with internet-facing services that decompress untrusted dataImages rebuilt and redeployed; managed-runtime vendors have confirmed their rollout
TodayShopifyTest checkout in a fresh private window with the real button, check Session Storage for __ctf_ keys, remove apps you don’t useClean on desktop and mobile; payment processor briefed if any doubt remains
TodayRailwayRotate in order: money, identity, data keys, the rest. Where you can’t revoke yet, cut the key’s permissions at the provider. Recreate Railway API tokensOld credentials confirmed dead at each provider; usage logs show nothing unfamiliar
This weekeMudhraUpdate CA bundles and runtimes, rebuild containers, replace any certificate chaining to the emSign ECC G3 rootNo certificate in your inventory chains to that root
This weekSBICustomers: verify any call or message through the official SBI app. Organizations: brief fraud and support teamsWarnings are out to customers and staff

Three incidents that patches can help with 

1. PHP2Shell

Two flaws in PHP’s core engine, CVE-2026-109618 and CVE-2026-109619, were disclosed on October 21 with fixed releases. Both are rated CVSS 9.2. Either can let an unauthenticated attacker run code on a vulnerable server, and one path can disclose process memory, which may contain sensitive information such as credentials. 

The bugs live in the PHP runtime, so updating WordPress, Drupal or any other CMS doesn’t touch them.

  • Fixes are in 8.2.35, 8.3.36, 8.4.27 and 8.5.12. PHP 8.1 and older are end of life, with source backports only for 7.4, 8.0 and 8.1.
  • Restart workers after patching. Distribution backports often leave the version string unchanged, so check your vendor’s advisory.
  • Per Wiz, frontier AI models helped chain the bugs into working exploits, and the code had been sitting there for years.
  • Many organisations, including government agencies in several countries and the Wikimedia Foundation, took sites offline as a precaution. (Verify the country list against the Reuters factbox before publishing.)

When heise reported, no successful exploits had been confirmed, though attacks had begun. Full details are in our PHP2Shell deep dive.

2. GitLab: CVE-2026-110264 (CVSS 10.0)

An integer overflow in the Onigmo regex compiler gives an unauthenticated attacker code execution on self-managed GitLab CE and EE, in versions going back to 7.0. No exploitation was confirmed as of October 22 and the CVE isn’t in CISA’s KEV catalog, but a pre-auth CVSS 10 rarely stays quiet.

  • If you upgraded on October 12 and closed the ticket, you’re exposed again. That patch fixed a different bug.
  • This is the fourth regex-engine RCE in about a month, all from the same researcher. We read that as an engine in an active disclosure cycle, not a one-off.
  • GitLab.com and eligible Dedicated tenants are already patched. Self-managed instances should move to 18.11.13, 19.0.10, 19.1.9, 19.2.9, 19.3.6, 19.4.3 or 19.5.1, depending on branch.
  • GitLab holds source code, CI/CD variables, deploy keys and runner credentials, so a foothold here doesn’t stay here.

The same release fixes 11 other issues. More in our GitLab deep dive.

3. Node.js: ten CVEs, one RCE

The project shipped fixes for 26.x, 24.x and 22.x on October 21, covering 10 CVEs (4 high, 3 medium, 3 low). The one to worry about is CVE-2026-111497, an out-of-bounds write in the Brotli decoder that allows remote code execution when attacker-controlled compressed data is decoded. Nobody has reported exploitation in the wild yet.

  • Three other high-severity flaws break TLS hostname checks and DNS name handling.
  • Upgrade to v22.23.4, v24.22.1 or v26.12.1 and rebuild images. Node 20.x and earlier are end of life and won’t be patched.
  • Until you can patch, consider stripping Content-Encoding: br from untrusted traffic.
  • The quiet one is CVE-2026-106074. Apps packaged as Single Executable Applications can replay the same “random” values from crypto.randomUUID() and randomInt(), so regenerate any secrets they produced.
  • The release also carries the CA update for the eMudhra compromise.

Full breakdown in our Node.js deep dive.

Assume the secrets are gone in these

4. LiteLLM

On October 21, a malicious litellm 1.107.0 reached PyPI and some Docker tags, carrying a credential stealer and a remote-code loader. According to LiteLLM’s report, it was live on PyPI for 1 hour 44 minutes. That was still long enough: stolen AWS credentials were reportedly in use within hours, with credential validation, Bedrock model enumeration and IAM discovery.

  • The attackers got in through three engineers’ GitHub accounts, apparently with stolen GitHub CLI OAuth tokens, and used them to approve a release. How the tokens were taken is still unknown.

If a host ran 1.107.0:

  • Isolate it, rebuild from a trusted image, and pin to 1.106.2.
  • Rotate everything it could reach: cloud roles, AI provider keys, database passwords, CI secrets.
  • Don’t stop at deleting the package. The credentials may already be gone.

Steps are in our LiteLLM deep dive.

5. Railway

Railway says it detected anomalous activity in the systems that store customer environment variables on the morning of October 21, and that an unauthorized party may have accessed encrypted variables and, for some, decrypted values. It recommends every customer rotate everything stored on the platform.

  • Rotation means a redeploy, and builds were paused for most of the first day. Enterprise builds returned at 04:00 UTC on October 22, Pro by 07:11, and Hobby, Free and Trial were still pending at 10:15.
  • Railway invalidated every API token at 04:17 UTC. Recreate yours before trusting your CI/CD.
  • Still open: whether the intruder’s access is closed, when it began, and whose variables were read. No email from Railway doesn’t mean you’re clear, and pausing your app doesn’t help, since credentials already read stay usable.
  • The Defiant reports that a developer tied a $370,000 theft to secrets stored on Railway. Railway hasn’t confirmed that, and we haven’t verified it.

The point we’d keep from this one: a variable swap closes the exposure for bearer API keys. It doesn’t for wallet keys, session and JWT signing secrets, application encryption keys or webhook signing secrets, and it can’t undo what an attacker already learned about your infrastructure. So:

  • Rotate in order of what each secret can move: money, identity, data keys, the rest.
  • Contain at the provider where you can’t revoke yet.
  • Scope replacements tightly and alert on first use. A new key written to a store that may still be open inherits the same risk.

The runbook is in our Railway deep dive.

Trust you inherited…sort of?

6. eMudhra

Eight intermediate CA certificates issued by eMudhra were protected by private keys so weak they could be recovered from the public certificates almost instantly. A proper key is a random 384-bit value. Each of these was an integer below 256, and researcher Scott Helme reported that one was the number 4, as quoted by Help Net Security. eMudhra says a faulty key-ceremony script produced a second, weaker set of keys that got used by mistake, and that it wasn’t breached.

  • An attacker holding those keys could issue fraudulent HTTPS certificates, though they’d still need to intercept traffic to use them.
  • Chrome and Firefox blocked the intermediates on October 17, the day Mozilla got the report. No malicious use had been confirmed as of October 21.
  • The gap is software that never gets revocation updates. Update OS packages, CA bundles and runtimes, and rebuild containers.
  • If you run websites, replace any certificate chaining to the emSign ECC G3 root before Chrome removes it.

7. Shopify apps

This wasn’t a confirmed breach of Shopify’s platform. Attackers abused third-party app configuration to inject a script that sent shoppers from the real Checkout button to a lookalike payment page, then on to the real one. HulkApps, Selleasy and Swym have each confirmed incidents between October 10 and 14.

It stayed hidden for three reasons:

  • The payload arrived as configuration data, not a changed script file.
  • It fired once per session.
  • Orders still completed, so revenue looked normal. Wallet checkouts like Shop Pay weren’t exposed.

What merchants should do:

  • Click the real Checkout button in a fresh private window, on desktop and mobile.
  • Look for __ctf_ keys in Session Storage.
  • Remove any app with a custom JavaScript field you don’t need.

Do a deep dive inside the HulkApps Shopify Checkout Hijack

8. A data leak: SBI

This isn’t a vulnerability, and we have no evidence linking it to the other seven. A threat actor calling itself Siriusim claimed over 375,000 CSV rows and 2,722 PDFs tied to State Bank of India.

  • SBI’s October 21 filing says a preliminary review of about 375,000 records found 3,897 with personal information, including names, mobile numbers, dates of birth, addresses and loan metadata.
  • SBI hasn’t attributed the leak to that actor and is still establishing the source.
  • Customers should expect phishing that uses real details, and verify any call or message through the official SBI app.

What they have in common

Six of the eight share something CVSS doesn’t capture: the failed component mattered because of how much trust sat inside it. This is our reading of the day, not a vendor finding.

IncidentWhat was concentratedBlast radius
PHP2ShellEvery request’s data, credentials included, in one worker processOne memory-disclosure path can expose other requests’ secrets
GitLabSource code, CI/CD variables, deploy keys, runner credentialsA foothold reaches everything GitLab can deploy to
LiteLLMEvery LLM provider key, plus cloud credentials on the hostOne bad install can empty the key ring
RailwayEvery customer’s environment variables in one storeOne intrusion puts every customer’s secrets in question
eMudhraThe authority to vouch for a site’s identityWeak keys could enable impersonation, given a network position
Shopify appsOne third-party script on the page where cards are typedA vendor’s admin tool became the checkout’s weakest link

Patching removes a flaw. It does nothing about concentration. The better question for a leadership team isn’t “are we patched?” but “if this one component were owned tomorrow, what would the attacker hold?” Teams that can answer with a list instead of a guess will triage a day like this much faster.

We found no public evidence that the eight were coordinated, though Railway ties its own incident to a broader campaign against platform companies. Until something says otherwise, we’d treat the clustering as coincidence plus shared root causes.

3 clocks, and only 1 is yours

Most programs track time to patch. This day ran on three clocks.

The exploitation clock (PHP2Shell, GitLab, Node.js) is the gap between disclosure and attack. AI-built exploits hint that it’s shrinking, and it’s the one your patch metrics already cover.

The exposure clock (LiteLLM, Railway, eMudhra, Shopify, SBI) started before anyone told you. LiteLLM’s malicious PyPI release was live for 1 hour 44 minutes; the affected Docker tags remained available for about 2 hours 34 minutes. Railway hasn’t said when access began. The Shopify incidents started on October 10, eleven days before the headlines. Only your logs can say what happened in that window, and nothing you patch today changes it.

The vendor clock (Railway, managed Node.js runtimes, Chrome’s eMudhra root removal, Shopify app vendors) runs on someone else’s schedule, and for end-of-life PHP and Node.js the fix never arrives. Your job is to verify and keep a fallback.

Ask for one number per clock: how fast do we patch, how far back can our logs answer “was this used?”, and which critical systems are waiting on a vendor?

What could an attacker see before you did?

We build external testing, so we start from the attacker’s side of the perimeter. Three of the eight are invisible or nearly so from there, and three more are only partly visible.

IncidentVisible from outside?
eMudhraYes. Certificate chains are public
Shopify appsWith effort. You have to test the journey, and the payload fired once per session
PHP2Shell, GitLabPartly. Versions are sometimes exposed; exploitability and unrestarted workers aren’t
SBIPartly, and only after the fact, through dark-web monitoring
Node.jsRarely. Runtime versions and container layers are seldom exposed
LiteLLM, RailwayNo. They live inside builds, runtimes and a platform’s secret store

External testing is the right control for the visible half. For the rest you need an inside-out record of what you run: a software bill of materials, a secrets inventory, and a list of every third-party script near checkout. No external scanner replaces that.

PHP2Shell testing DAST scanner Astra

What would have broken the chain

“Patch, rotate, monitor” isn’t specific enough for a security team. Below are controls that would have interrupted the attacks where the chain is known, and where each one runs out. We don’t know which the victims had, so read this as analysis of controls, not criticism of anyone.

For LiteLLM’s release pipeline: trusted publishing pinned to one repository and workflow, provenance attestations, alerts on workflow-file changes and branch-protection overrides, and a cooldown on new releases. Even a 24-hour delay would have skipped a window under two hours. The limits are that three compromised reviewers can satisfy a required-review rule, and cooldowns delay real security fixes, so exempt vetted urgent updates.

Note: Provenance attestations help identify which workflow produced an artifact, but do not by themselves prove that the checked-out source was untampered.

For stored secrets (Railway, LiteLLM): short-lived credentials through OIDC federation so stolen values expire, provider-side scoping such as spend caps and IP conditions, and canary credentials that tell you when a store has been read and used. None of that scopes signing, encryption or webhook secrets; not every integration supports federation, and canaries detect without preventing.

For the storefront: a Content Security Policy, PCI DSS 4.0.1 requirements 6.4.3 and 11.6.1 (script inventory and tamper detection), and synthetic checkout tests. The scripts were authorized and the windows were short (Swym about 1 hour 50 minutes, Selleasy about seven hours), so a weekly tamper check misses both.

Ask app vendors about MFA and least privilege on their admin tools before you install, since you can’t enforce it afterwards.

For certificate trust: Certificate Transparency monitoring, and trust-store reduction or pinning for clients you control. CAA records do nothing against an attacker holding a trusted intermediate’s key, and absence from CT logs isn’t proof of safety.

For PHP2Shell, GitLab and Node.js the control is the patch plus less exposure while you roll it out: a WAF as a stopgap, GitLab behind a VPN or allow-list, and decompression of attacker-controlled data only where you must.

What we don’t know

Several claims above rest on a single vendor statement or report. This is where the evidence stops.

  • PHP2Shell, GitLab, Node.js: Exploitation status is still a snapshot, not an all-clear: PHP2Shell attempts and PoCs have been reported, while GitLab and Node.js had no reported exploitation as of October 22; assume this can change quickly.
  • LiteLLM: How the developer tokens were stolen, how many installs ran the stealer, and how much data left.
  • Railway: Details of when access began, whether it’s closed, and whose variables were read. The status page recorded an outage from 07:24 UTC on October 21, and the security notice came at 21:59, 14 hours 35 minutes later. Public sources don’t say whether the two are related.
  • eMudhra: How long the keys were exposed, whether unlogged forged certificates were ever used, and whether Chrome’s root removal is done or planned.
  • Shopify apps: The exact mechanism, how many stores and shoppers were affected, and the full list of apps.
  • SBI: Whether the dataset is authentic or current, and what’s in the claimed PDFs.

The AI angle

AI helped researchers turn long-standing PHP bugs into working exploits, which narrows the gap between a flaw existing and a flaw being exploited. 

AI infrastructure is a target too: LiteLLM sits between applications and their provider keys, and Railway tied its incident to attacks on AI inference providers. Defenders have the same tools for finding and validating exposure faster, and we’d encourage using them.

Five questions for Monday’s leadership meeting

  1. If our most trusted component were compromised tomorrow, what would the attacker hold? Can we list every secret in it?
  2. Which critical systems can only be fixed by a vendor, and what’s our fallback while we wait?
  3. Can we revoke a leaked key in minutes without taking production down?
  4. How far back can our logs answer “was this used?”
  5. Do we have an inventory of what runs inside our builds and runtimes: packages, trust stores, and third-party scripts near checkout?

Where can Astra help?

Start with the fix: patch, restart workers, verify the running version, and rotate what may be exposed. Beyond that, here’s where we can help.

Find your PHP2Shell exposure quickly. Astra’s Emerging Threat Scan and Lightning Scan run targeted checks for newly disclosed vulnerabilities, so they’re the fastest way to check your internet-facing assets. Our Full Scan covers PHP2Shell too. A scan tells you where you’re exposed, and a clean result is a starting point, not a guarantee. You should still audit the PHP versions you run and upgrade.

PHP2Shell testing by Astra security

Check PHP2Shell exposure for free: Use Astra’s PHP2Shell Checker to test a public URL against the fixed PHP releases (8.2.35, 8.3.36, 8.4.27, and 8.5.12). It requires no account, but a clean result only confirms the detected PHP version is patched; it is not a full security assessment. 

For hidden headers or internal systems, verify the installed PHP build directly. 

Check whether it’s actually exploitable. Autonomous Pentest tests whether an exposed application can be attacked in your setup, which helps you decide what to fix first.

Make sure the fix holds. Through our PTaaS platform, new exposure is caught as it appears, and findings are re-tested after you patch. They’re tracked in one dashboard, and a human tester handles the judgment calls. That matters on a day like this, when you need to know the patch worked and not just that it was applied.

For GitLab, our scans report version disclosure on exposed instances, and an Emerging Threat Scan is a quick way to see what your internet-facing assets reveal.

After a credential incident like Railway or LiteLLM, a targeted assessment can confirm that old credentials are dead, no attacker-created users, keys or roles remain, and your cloud IAM can’t be escalated from a single leaked key.

Final Thoughts

October 21 showed that “are we patched?” is only the first question after an incident. Three of the eight incidents could be handled with an upgrade. For the other five, the exposure had started before anyone told you, sat inside a vendor’s platform, or was already out in the open, and a patch changes none of that.

The practical order of work is simple. Start with what exposes the most systems: find your PHP runtimes, patch them, and verify what’s actually running. Rotate secrets by what they can move, starting with money. Then work through the vendor-dependent items, and keep a fallback while you wait on them.

The harder lesson sits underneath. The failed components mattered because so much trust was concentrated in them: a worker process, a CI system, an AI gateway, a secrets store, a certificate authority, a checkout page. 

The next incident will hit a different component, and the teams that handle it fastest will be the ones that can say what an attacker would hold if it were compromised, how far back their logs can answer “was this used?”, and which systems only a vendor can fix.

Several questions are still open, including Railway’s intrusion status, how LiteLLM’s tokens were stolen, whether the eMudhra keys were ever used, and the full scope of the Shopify and SBI incidents. We’ll keep updating this post as vendors publish more. If you’re working through a response and want a second pair of eyes on your exposure, we’re glad to help.

Update log

Oct 22: Initial post. We’re tracking Railway’s intrusion status, how LiteLLM’s tokens were stolen (and its enterprise disclosure, scheduled for October 27), any use of the eMudhra keys, Chrome’s decision on the root, SBI’s investigation, and the full list of affected Shopify apps.

Sources

  • Astra deep dives: PHP2Shell, LiteLLM, GitLab, Node.js, Railway
  • Primary sources: LiteLLM incident report, Railway security disclosure, Node.js October 2026 security releases, Beazley Security advisory, Wiz Research, PHP advisories for CVE-2026-109618 and CVE-2026-109619, Mozilla dev-security-policy thread, Help Net Security, Google’s response on eMudhra, HulkApps, Selleasy and Swym statements, SBI regulatory filing, The Hacker News, The Defiant, Reuters, heise