PHP2Shell Explained: What Docker Users Must Update
PHP2Shell is two critical PHP bugs, CVE-2026-109618 and CVE-2026-109619, that allow remote code execution back to PHP 5.4. Here is how they work and what Docker users must update.

7 min read
Came here from Instagram, LinkedIn, X or YouTube? Here is the full source list you came for. Everything below is built from these, nothing else.
The announcement
Think of PHP as a hotel, and every web request as a guest checking in for one night.
The guest gets a room. Housekeeping preps it. The guest leaves, the room gets cleaned, and the next guest walks into a fresh room. That loop runs thousands of times a day and nobody thinks about it.
Now picture two ways the hotel can get it wrong.
In the first, housekeeping gets pulled away halfway through prepping a room. Then the checkout inspector walks in and reads whatever notes are lying on the desk, notes that nobody from this stay ever wrote.
In the second, a guest checks out, but the front desk never deactivates their key card. The room gets handed to someone new. The old card still opens the door.
That is PHP2Shell. Two bugs in how PHP looks after request memory, and both let an attacker run their own code on your server.
Key takeaways
- PHP2Shell is two critical bugs, CVE-2026-109618 and CVE-2026-109619, in PHP core. Both allow remote code execution.
- They reach back to PHP 5.4: supported 8.2 to 8.5, plus end of life 5.x, 7.x, 8.0 and 8.1.
- The fixed releases are 8.2.35, 8.3.36, 8.4.27 and 8.5.12, or anything later in the same branch.
- Docker says updating is the only complete mitigation. If you can't update right away, take the system offline.
- Docker Official Images and Docker Hardened Images were updated within 24 hours of the upstream patches.
What is PHP2Shell?
PHP2Shell is the common name for two vulnerabilities Docker started tracking on Tuesday, October 20, 2026. Docker published its security update two days later, on October 22.
The important line from that post: this is a flaw in PHP itself, not in Docker's systems. But if you build on PHP images or packages from Docker Hub, it lands on you anyway.
The bugs sit in PHP core. That is the part every PHP app shares, so it doesn't matter which framework you use on top.
Docker's post also points to a detailed report from the PHP Foundation on how the bugs were found, and recommends reading it for full context.
How do the two PHP2Shell bugs work?
Back to the hotel. Here is each bug, step by step, using Docker's own description.
CVE-2026-109618: the half-cleaned room
- A request comes in and PHP starts working on it.
- Partway through, PHP runs out of memory and aborts the request.
- On some code paths, that abort leaves a chunk of memory uninitialized. Nothing from this request was ever written there.
- PHP's cleanup step runs and reads that memory anyway.
That is the inspector reading notes nobody from this stay wrote. Whatever happens to be sitting in that memory is now treated as real data.
CVE-2026-109619: the key card that still works
- PHP frees a piece of memory when it is done with it.
- PHP's internal state keeps pointing at that freed memory.
- A later request comes along and uses that stale state.
That is the old key card still opening a room that now belongs to someone else. This class of bug is usually called use after free.
Why that becomes remote code execution
Docker says attackers have multiple ways to trigger either condition, and to turn it into remote code execution.
In plain words: an attacker can push PHP into one of these broken states on purpose, then use it to run their own code inside your PHP process. That is where the "Shell" in the name comes from.
Which PHP versions are affected?
All of these:
| Branch | Status | Fixed release |
|---|---|---|
| 8.5 | Supported | 8.5.12 or later |
| 8.4 | Supported | 8.4.27 or later |
| 8.3 | Supported | 8.3.36 or later |
| 8.2 | Supported | 8.2.35 or later |
| 8.1, 8.0 | End of life | No fixed release listed |
| 7.x, 5.x (from 5.4) | End of life | No fixed release listed |
Look at the bottom three rows. PHP shipped fixes for four branches only. If you're on 8.1 or older, there is no patched release in your branch in the list. Updating means moving to 8.2 or later.
That's the expensive row, and probably the one you've been putting off.
What did Docker change in its images?
Two sets of images, two updates.
Docker Official Images have been updated and released to Docker Hub, and mirrored to Amazon ECR. If you pull from either, Docker says to update immediately.
Docker Hardened Images (DHI) have been updated and released to Docker Hub. The supported PHP versions moved like this:
| Before | After |
|---|---|
| 8.2.34 | 8.2.35 |
| 8.3.35 | 8.3.36 |
| 8.4.26 | 8.4.27 |
| 8.5.11 | 8.5.12 |
Docker says these were released within 24 hours of the upstream patches, after passing its DHI testing and verification processes.
One thing worth being clear about. Docker updating the image on Docker Hub does not update the containers you're already running. Your running containers were built from the old image. They stay vulnerable until you pull, rebuild and redeploy.
When should you update, and when should you go offline?
This is where the explainer turns into a decision.
Update now if you run any PHP from 8.2 to 8.5, inside Docker or not. Docker's guidance applies to everyone using PHP, not just its customers. A patch release inside your current branch is the smallest change you'll ever make for a critical bug.
Plan a branch upgrade if you're on 8.1, 8.0, 7.x or 5.x. There's no fixed release in your branch on the list, so the fix is moving to a supported one.
Take the system offline if you can't update right away. Docker is blunt about this: there is no other comprehensive remediation for the affected versions. It says this is also the FBI's guidance and that of numerous experts across the security community.
What doesn't count as a fix. Docker's post lists exactly one complete mitigation, which is updating. It names no config flag, firewall rule or workaround that closes the hole. If someone sells you one, treat it as a delay, not a fix.
When this isn't your problem. If nothing you run uses PHP, from Docker Hub or anywhere else, PHP2Shell doesn't touch you. Just check before you assume. PHP turns up in base images, sidecars and old internal tools more often than you'd expect.
How do you check and fix a PHP container?
Three steps. Check the version, rebuild on the patched base, check again.
Step 1: see what PHP your image actually has.
docker run --rm --entrypoint php myapp:latest -r 'echo PHP_VERSION, PHP_EOL;'
Swap myapp:latest for your own image. This prints the real PHP version inside it, which matters more than whatever tag you think you pinned.
Step 2: compare it against the fixed releases. Here is a small script you can drop into your image or your CI. It uses only the four versions from Docker's post.
#!/bin/sh
v=$(php -r 'echo PHP_VERSION;')
case "$v" in
8.2.*) min=8.2.35 ;;
8.3.*) min=8.3.36 ;;
8.4.*) min=8.4.27 ;;
8.5.*) min=8.5.12 ;;
*) echo "$v: no patched release in this branch, move to 8.2 or later"; exit 1 ;;
esac
if [ "$(printf '%s\n' "$min" "$v" | sort -V | head -n1)" = "$min" ]; then
echo "$v: patched (needs $min or later)"
else
echo "$v: VULNERABLE, update to $min or later"
exit 1
fi
The sort -V line does a version-aware comparison. If the minimum sorts first (or is equal), you're on the fix or past it. The non-zero exit means your CI fails loudly instead of shipping the old version quietly.
Step 3: rebuild against the updated base image.
docker build --pull --no-cache -t myapp:latest .
--pull forces Docker to fetch the newest base image instead of reusing the copy it cached last month. --no-cache stops it reusing old layers. Then run Step 1 again, see a patched version, and redeploy.
If you skip the redeploy, you've done all the work and fixed nothing. The running container is still the old one.
What if the updated images don't work for you?
Docker says to contact Docker Support at app.docker.com/support/contact if you have trouble getting the updated images or migrating to the new versions.
That's most useful for the end of life crowd. A move from 7.x to 8.2 isn't a patch, it's a migration, and you shouldn't do it alone at midnight.
FAQ
What is PHP2Shell?
PHP2Shell is the common name for CVE-2026-109618 and CVE-2026-109619, two critical vulnerabilities in PHP core. Both are flaws in how PHP manages request memory, and both can be turned into remote code execution. Docker began tracking them on October 20, 2026.
Which PHP version do I need to be safe from PHP2Shell?
You need PHP 8.2.35, 8.3.36, 8.4.27 or 8.5.12, or a later release in the same branch. Versions 5.x, 7.x, 8.0 and 8.1 are end of life, and no fixed release for those branches is listed. Moving to a supported branch is the way out.
Is Docker itself vulnerable to PHP2Shell?
No. Docker says the vulnerability is in PHP, not in Docker's systems. The risk is to anyone running PHP in their apps, including PHP images and packages from Docker Hub, Docker Official Images and Docker Hardened Images, which Docker has already updated.
What if I can't update PHP right away?
Docker strongly recommends taking the system offline until you can update. It says there is no other comprehensive remediation for the affected versions, and that this matches the FBI's guidance. Updating is the only complete fix.
Run the version check on every PHP image you own today, then rebuild anything that fails. For more practical tooling, browse the free tools on Art of Code, and for more posts like this one, see our engineering articles.
Written by Adithya Guttha, Founder of Art of Code.
Sign in to like and save posts.
Keep reading



Discussion
Comments (0)
Want to join the conversation?
Sign in to commentNo comments yet. Be the first to comment!