PHP2Shell PHP Vulnerability & LiteLLM Hack: What to Patch

Mor Weinberger
Mor Weinberger
Oct 21, 2026 | 12 Minutes
PHP2Shell PHP Vulnerability & LiteLLM Hack: What to Patch

Key takeaways

  1. Two different attacks landed on October 21, 2026: a pair of critical memory-safety flaws in the PHP engine (CVE-2026-109618 and CVE-2026-109619, both CVSS 9.2) and a malicious LiteLLM 1.107.0 wheel on PyPI carrying an infostealer and a remote access trojan.
  2. Patching PHP is the only complete fix. Upgrade to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35. The ini-level workarounds only narrow the attack paths.
  3. Treat anything that installed LiteLLM 1.107.0 as compromised. Isolate it, pin to 1.106.0, and rotate every secret it could reach.
  4. Your container image decides how bad a bad day gets. Fewer packages, no shell, non-root workers and tight resource limits shrink what an attacker can do after landing code execution.
  5. Rebuild speed is the metric that matters. Teams whose images are rebuilt within hours of an upstream fix spend this week verifying, not scrambling.

{{cta_slack}}

One Wednesday, two very different attacks

On Tuesday evening, October 20, a post on Hacker News claimed that two critical remote code execution bugs in PHP were days away from public disclosure. Within hours, the PHP security team posted an advance notice and pulled its release forward to 14:00 UTC the next day. By the time patches shipped on Wednesday, Cloudflare said it was already seeing early attack attempts, and Sansec was predicting mass exploitation within 15 minutes of the release.

The researchers behind the find, Wiz Research working with Calif and OpenAI's Codex Security team, called the bugs PHP2Shell. The name fits. The flaws reach back more than a decade of PHP releases, and Wiz notes that PHP still runs roughly 70% of the websites on the internet.

The same day, a second incident surfaced in a completely different corner of the stack. OX Security reported that LiteLLM 1.107.0, a release of one of the most popular open source LLM gateways, had been published to PyPI with an infostealer and a remote access trojan hidden inside it.

One is a PHP vulnerability in the runtime you inherit from your base image. The other is a poisoned dependency you pull in at build time. Both end in the same place: attacker code running inside your container, right next to your secrets. This post walks through each incident, what to do about them this week, and what a secure PHP container image changes when the next one lands.

What went wrong inside PHP

The two CVEs, CVE-2026-109618 and CVE-2026-109619, cover four related memory-safety bugs in the PHP engine itself. That detail matters: you do not need a vulnerable plugin or a sloppy application to be exposed. According to Wiz's write-up, even a "Hello World" page on an affected PHP version can be a target.

Every bug traces back to the same weak spot: how PHP cleans up when a request dies from a fatal error, especially an out-of-memory error. A request that ends abruptly can leave stale internal state behind. The next request handled by the same worker then picks up that stale state, and that is where an attacker gets a foothold.

Bug What breaks What researchers demonstrated
Upload-progress unserializer use-after-free Freed memory is reused by a later request Unauthenticated RCE on WordPress, Drupal and Joomla (chained with the memory leak)
Remote process-memory disclosure A stale session pointer leaks worker memory inside the PHPSESSID cookie Data from other users' requests, even in apps that never call session_start()
Fatal-error backtrace use-after-free The next request reads a backtrace that was already freed RCE on Drupal
OPcache type confusion Shared OPcache state falls out of sync across workers RCE on WordPress

Wiz ran its proof-of-concept exploits against the stock wordpress, drupal and joomla images on Docker Hub, which tells you exactly where defenders should look first. The memory disclosure bug is quietly the scariest of the four. Without ever running code, an attacker can read worker memory that may hold passwords, tokens, API keys and certificates.

Who is exposed

Every way of serving PHP over the web is affected: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP rates mod_php as the highest risk, because a single unauthenticated request can trigger an exploit before any application code runs. PHP-FPM is less exposed, but The Hacker News reports that it is still susceptible, with one flaw reaching code execution through an application-dependent path.

The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and older no longer get official releases, although the PHP team published source backports for 7.4, 8.0 and 8.1. One more trap: Linux distributions often backport the fix under an older-looking version number, so check the package changelog for the CVE IDs instead of trusting the version string.

LiteLLM 1.107.0: a clean repo and a poisoned wheel

While PHP teams were racing to patch, OX Security flagged a malicious LiteLLM release on PyPI. It is the second time this year the project has been hit. In March, versions 1.82.7 and 1.82.8 were compromised in the TeamPCP campaign, which we covered in our roundup of March's supply chain attacks. OX says this LiteLLM supply chain attack used different tooling and infrastructure.

The detail that should worry every platform team is where the payload lived. The malicious code was injected only into the published wheel. The GitHub repository and the clean source never contained it, so a code review of the project would have found nothing.

Once installed, the package does not wait to be imported. It plants code in sitecustomize.py, so it runs every time Python starts on that machine, even in projects that never touch LiteLLM. From there it does two jobs:

  • Infostealer: it collects environment variables, AWS and Azure credentials, GitHub tokens, browser passwords and cookies, shell and Python history, credentials for AI coding tools like Claude Code, GitHub Copilot and Cursor, and secrets stored in a LiteLLM proxy's database.
  • Remote access trojan: it checks in with its operator roughly every hour, reads its command server address from a GitHub URL, and can run any new code it receives.

Stolen data goes to litellm[.]dev, a lookalike domain registered by the attacker. PyPI has quarantined the release, and 1.106.0 is the last known safe version.

LiteLLM is an especially painful target because of where it sits. An LLM gateway exists to hold the keys to every model provider your company uses, usually alongside cloud credentials. We dug into why this layer keeps getting targeted in AI supply chain security: where the new risks actually come from.

Why the container image decides the blast radius

Put the two incidents side by side and the pattern is hard to miss. One attacker gets in through the language runtime. The other gets in through a library. Neither cares much about your application code. What both care about is what they find once they are inside the container.

An attacker who lands code execution as the PHP worker user, or whose RAT starts with Python, immediately starts looking for the same things:

  • A shell and a package manager to download and run second-stage tools
  • Network utilities like curl or wget to reach the command server
  • Root access or a writable filesystem to persist across restarts
  • Long-lived credentials in environment variables, mounted files or the cloud metadata endpoint
  • Other unpatched CVEs in the same image to chain into privilege escalation

A typical PHP Docker image built on a general-purpose Linux base hands over most of that list by default. Every extra package in the image is something the attacker can use, and something your scanner will keep flagging long after this week's patch. We broke down that hidden cost in Docker base images: the hidden risk in your container stack.

The PHP advisory itself points in the same direction. Its interim guidance recommends container or cgroup memory limits that kill only the affected worker, and warns against process-level limits like RLIMIT_AS that can trigger the vulnerable path. In other words, how you build and run the container is part of the defense. That is the real argument for hardened container images: they do not stop every bug, but they remove most of the tools an attacker reaches for next.

What a hardened PHP image actually looks like

Hardening is not one setting. It is a set of decisions made when the image is built, so that nobody has to remember them at 2 a.m. during an incident. For a production PHP Docker image, those decisions look like this:

  • Only what PHP needs to run. The PHP runtime, the extensions your app actually loads, and FPM or the web server. No shell, no package manager and no compilers in the final stage. Multi-stage builds make this practical, as we explain in Dockerfile best practices that reduce your attack surface.
  • Non-root by default. Workers run as an unprivileged user, ideally with a read-only root filesystem and only the writable paths the app needs.
  • A supported PHP branch, rebuilt fast. The image tracks 8.2 through 8.5 and is rebuilt within hours when an upstream fix lands, not whenever the next scheduled build happens to run.
  • Conservative ini defaults. Features you do not use stay off. If your app does not show upload progress, session.upload_progress.enabled should already be 0. Set post_max_size to what you need and turn off expose_php.
  • An SBOM and a signature for every build. When the next advisory drops, "are we affected?" becomes a query instead of a week of docker exec sessions. Our guide on how to generate an SBOM for a container image covers the mechanics.
  • Resource limits set at the container level. Memory limits enforced by the orchestrator contain a misbehaving worker without touching the rest of the pod.

None of this would have made the PHP engine bugs disappear. What it does is shrink the window between disclosure and a patched deployment, and shrink what an attacker can do inside that window. If you are moving off the official images, our step-by-step migration guide walks through the process.

What to do this week

The two incidents need different responses, but both start with the same question: where is this running? Begin with an inventory, then work through each one.

For the PHP flaws

Start by listing every image that ships PHP. That means more than your own php base images. Count WordPress, Drupal, Joomla, Moodle, FrankenPHP and any vendor appliance that serves a PHP admin panel. Then check the version inside each one:

# Print the PHP version inside an image
docker run --rm --entrypoint php your-registry/app:tag -v

Next, move every image to a fixed release and rebuild and redeploy, not just pull. Because the bugs abuse state that lives in long-running workers, restart every PHP-FPM pool and Apache process after the upgrade.

If something cannot be patched today, PHP's interim measures narrow the attack paths without closing them. Set session.upload_progress.enabled=0, keep post_max_size low, enforce request size limits at your proxy, and on PHP 8.5 set fatal_error_backtraces=0. Then restart the workers. WAF rules from Cloudflare, AWS, Google and others buy time too.

Finally, hunt. Wiz and other researchers suggest watching for multipart requests followed by memory-limit errors or bursts of HTTP 500s, unusually large PHPSESSID cookies in responses, and unexplained worker restarts. Application logs may show little, because the bugs live below the application layer. If you find signs of probing, assume secrets in worker memory were exposed and rotate them.

For LiteLLM 1.107.0

Search lockfiles, container images and CI caches for the bad version:

grep -rn "litellm==1.107.0" requirements*.txt poetry.lock uv.lock
pip show litellm | grep Version

Any machine or container that installed it should be treated as fully compromised. Isolate it, rebuild from a clean state with LiteLLM pinned to 1.106.0, and rotate every secret it could reach, including LLM provider keys, cloud credentials, database passwords, SSH keys, CI tokens and any provider keys stored in a LiteLLM proxy database. Block outbound traffic to litellm[.]dev while you investigate.

For the longer term, pin versions and add a short delay before new releases can be installed. We cover the rest of the checklist in how to ensure you use a safe PyPI package.

How Echo handled October 21

For Echo customers, the PHP part of the day was short. Echo shipped the fixed PHP packages less than three hours after the upstream fix landed, and our php 8.2, 8.3, 8.4 and 8.5 images were rebuilt the same afternoon. Customers pulling those tags got the patched runtime without opening a ticket or editing a Dockerfile.

That speed is not a one-off. Echo commits to a 7-day SLA for critical and high CVEs, and our average time to remediate is under 12 hours. We explain why automated patch SLAs change the risk math in how automated patch SLAs reduce enterprise risk.

There is a bigger trend behind this week's news, too. Wiz credits frontier AI models with helping a single researcher find these PHP bugs in about a week. When AI makes deep runtime bugs this cheap to find, disclosures will keep arriving faster, and sometimes, as on Tuesday night, before the patch is ready. That is why we built Echo Frontier, which patches AI-found zero-days in our images before public disclosure.

The LiteLLM incident is a reminder that the image is only half of the story. The payload lived in the published wheel, not in the source, which is a strong case for libraries that are built from audited source and vetted before they ever reach your registry.

If you want a secure PHP container image that is minimal, non-root, signed and patched within hours, talk to the Echo team or see how we compare in Echo vs. Docker Hardened Images.

FAQ

What are CVE-2026-109618 and CVE-2026-109619?

They are two critical memory-safety vulnerabilities in the core PHP engine, disclosed and patched on October 21, 2026, and each rated CVSS 9.2 (v4.0). They stem from how PHP cleans up after fatal and out-of-memory errors mid-request, which can leave stale state for a later request to reuse. Researchers demonstrated unauthenticated remote code execution and memory disclosure against WordPress, Drupal and Joomla containers.

Which PHP versions fix the flaws?

PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 are the first fixed releases on each branch. PHP 8.1 and older no longer get official releases, although the PHP team published source backports for 7.4, 8.0 and 8.1. Linux distributions may ship the fix under an older-looking version number, so check the package changelog for both CVE IDs instead of trusting the version string.

Is PHP-FPM safe from these bugs?

No. PHP-FPM is less exposed than Apache with mod_php, which PHP rates as the highest risk because a single unauthenticated request can trigger an exploit before application code runs. On FPM, one flaw is considered susceptible without a public full exploit, and the other reached code execution through an application-dependent path. FrankenPHP, php-cgi and LiteSpeed are affected as well, so patch all of them.

Can I protect PHP without patching right away?

Only partially. PHP suggests disabling session.upload_progress, keeping post_max_size low, enforcing request size limits at the proxy, and on PHP 8.5 setting fatal_error_backtraces=0, then restarting every worker. Avoid RLIMIT_AS and RLIMIT_DATA, which can trigger the vulnerable path. WAF rules from Cloudflare and others buy time. None of these block every variant, so treat them as a bridge to the patched release.

What should I do if I installed LiteLLM 1.107.0?

Assume the machine or container is fully compromised. Isolate it first, then rotate every secret it could reach: LLM provider keys, cloud credentials, database passwords, SSH keys, CI tokens, and any provider keys stored in a LiteLLM proxy database. Pin LiteLLM to 1.106.0, rebuild affected images from a clean state, and block traffic to the lookalike litellm[.]dev domain.

How does a hardened image help if PHP itself is vulnerable?

It does not remove the bug. Only a patched PHP release does that. What it changes is what happens next. With no shell, no package manager, a non-root worker and a read-only filesystem, an attacker who lands code execution has far fewer tools for fetching payloads, persisting or moving laterally. An image rebuilt within hours of upstream fixes also shortens the exposure window itself.

Frontier models can now find and exploit zero days in your code

Find out what to do when there's no CVE, scanner alert or fix available yet.

What are the 7 blind spots in your vulnerability scans?

Discover when "0 vulnerabilities" doesn't actually mean you're clean.

Read now →

Looking for hardened PHP container images?

Start pulling hardened PHP images today

Ready to eliminate vulnerabilities at the source?