News ·

PHP2Shell (CVE-2026-109618/109619), Part 2: How AI Found It, How to Patch It

How we patched more than 150 PHP sites for PHP2Shell: six hours of AI-assisted preparation, human sign-off on every change, under 30 minutes offline.

PHP2Shell, covered in part one, meant patching more than 150 PHP sites before attackers caught up. This part is a short account of how that happened, what the AI did, what the humans did, and what we are taking away from it. We spent six hours working through every PHP site we run, starting as soon as PHP posted its advance notice. When the fixed builds landed on October 21, we were ready to apply them. Every site was back online in under 30 minutes. Part one has the background.

Reading the notice

We heard early because our team subscribes to the security channels of PHP and of every platform we run on it, including Drupal, WordPress, and Moodle. The advance notice reached us directly, not through the news cycle the next morning.

The advance notice told us very little: two critical flaws, CVSS 9.2, a release at 14:00 UTC the next day, and a warning to prepare now. It gave no affected versions and no technical details. That was enough to make the first decision: do not wait for the details; prepare as if every PHP runtime we own is affected.

We run more than 150 PHP sites on platforms including WordPress, Drupal, and Moodle, for our own organizations and for clients. They do not all run the same way, by design. A few sites that need the strongest isolation run on dedicated VMs. Others share VMs, each site in its own container, so they stay separated while sharing hardware. The whole fleet runs on Google Cloud and is defined in Terraform. We use Terraform together with the gcloud CLI and other Google Cloud command-line tools to provision, update, and deploy it, so the code describes what should exist and where.

That mix shaped the job’s scope. Isolating each site is what matters, and a dedicated VM is only one way to get it, and the most expensive one. For the containerized sites, patching meant rebuilding a small number of base images and redeploying, rather than touching each site by hand. The dedicated VMs needed their own runtime updates, one by one. Terraform gave us a starting inventory we could trust and a repeatable way to roll changes out.

How the harness worked

The speed came from our AI-led SDLC harness: AI agents did the repetitive engineering, and humans owned every decision that mattered. In practice:

  1. Protection at the edge first. Our sites use Cloudflare for DNS, CDN, and WAF, so the first step was confirming that every PHP site was proxied through Cloudflare with its managed WAF rules enabled. That meant each site was covered automatically when Cloudflare’s PHP2Shell rules went live at 03:02 UTC on October 21 (Cloudflare). We treated it as the first layer of protection while we patched, not a replacement for patching.
  2. Inventory, verified against reality. We started from our Terraform definitions and site list, then had agents cross-check them against live checks on each VM and container: the PHP runtime actually running, its version, how it was installed, and what it serves. Where the code and the servers disagreed, the servers won, and the code was corrected to match.
  3. Triage. Each workload was ranked by exposure: internet-facing mod_php first, end-of-life branches flagged for upgrade, internal tools last. An engineer signed off on the ranking before anything else moved.
  4. Interim mitigation. Once PHP published its advisory, agents drafted its temporary php.ini changes and request-size limits for the sites they applied to. An engineer reviewed each one, because some settings, such as upload limits, can break real features.
  5. Patch preparation. For the containerized sites, agents prepared updated base images for each platform, ready to rebuild on the new PHP builds as soon as they were published. For the dedicated VMs, agents prepared the runtime package updates host by host. Both were rolled out with Terraform and the gcloud CLI, not as ad hoc server changes.
  6. Testing. Automated regression and smoke tests ran against staging for every site. Once the advisory confirmed that the fix makes PHP stricter when it runs out of memory, memory-limit checks ran against the fixed builds too.
  7. Human approval. An engineer reviewed every change before it touched production. Nothing reached a live server on an agent’s say-so alone.
  8. Staged rollout and verification. We patched in waves, restarted every worker, then rescanned to confirm each host reported a fixed version.

Release day: under 30 minutes offline

When PHP published the fixes on October 21, the work left was execution. Each site went into a short maintenance window: update the runtime, restart Apache and PHP-FPM, run the smoke tests, and bring it back. We chose brief planned downtime over running unpatched behind a firewall, because PHP’s advisory is clear: only updating is a complete fix, and every worker must be restarted (PHP security advisory).

The longest any site stayed offline was under 30 minutes. Most came back much faster.

What the AI did, and what the humans did

The agents:

  • Cross-checked our inventory against live server checks and flagged every mismatch
  • Drafted mitigations, package updates, and image changes
  • Ran the test suites and verification scans, and summarized the results

The engineers:

  • Decided to prepare before details were public
  • Approved the triage order and every change before production
  • Chose when to take each site offline, and for how long
  • Owned the call on anything the tests flagged

What we are taking away

  • Subscriptions bought us the day. Being on the PHP, Drupal, WordPress, and Moodle security channels meant we started on October 20, not the morning of October 21 alongside everyone else.
  • Edge protection bought us time. With every site already behind Cloudflare’s WAF, attack traffic met a filter before it reached our servers while we prepared the real fix.
  • Architecture decides the size of the patch job. We patched containerized sites by rebuilding a few base images; each dedicated VM was its own job. Isolation per site matters more than a VM per site, and containers give most sites that isolation at a fraction of the patching effort.
  • Terraform is the inventory, if you keep it honest. Our code was a strong starting point, but we trusted live checks. Keeping the two in sync is now a standing job.
  • End-of-life versions are debt with interest. Every host on an old branch needed more work than the rest. Upgrading on a schedule is cheaper than upgrading in an emergency.
  • Human checkpoints did not slow us down. Because the agents did the preparation, reviews were quick: engineers were approving finished work, not doing it.

The lesson is not that AI did the work for us. It is that AI let a small team do in hours what used to take days, without cutting the human checks that keep production safe.