← All posts

A second place to ship, and a patch window measured in hours

On 21 October a platform's builds and deploys were paused while a PHP release landed after exploits were already circulating. What a builder running an app or an agent on their own VM should have ready: a second place to deploy, and a way to read a security bulletin in minutes.

On 21 October a platform's builds and deploys stopped going out, and a PHP security release landed with exploits already circulating before the release existed. Neither is unusual alone. Together they point at one question for anyone running an app or an agent on a VM they control.

The question is not how to depend on nobody. It is whether you know who you depend on, and whether you have two things ready: a second place to deploy, and a patch window measured in hours rather than days.

What the sources say

Dennison Bertram writes, quoting the status page, that builds and deploys had been paused "since about 3:24 AM Eastern", and that at "a little after 3 PM" the dashboard and API were still affected with no new builds going out "in any region". The incident, as the page titles it, lists affected builds in US West, EU West, Southeast Asia and US East. He says plainly that he is only repeating the status page, and it was written mid-incident.

His point is about his own setup, not about the platform. His agents kept pushing a fix, asking for a deploy, getting an error and retrying, because the agent "was handed one place to deploy, and that place is closed". He maintains an open-source deploy tool himself and suggests giving the agent a second target plus one instruction: "If the main platform's deploys are failing and its status page shows an incident, deploy to $AH_URL instead and tell me you did." His framing is the part worth keeping: "two places that fail for different reasons, not one place that never fails".

A commenter signing as Oleksandr names the hole: an agent holding two targets can still choose wrong, because a failed deploy is not evidence that the platform is down. The condition must be checkable - the status page - not the error the agent happens to receive.

Simon Willison's link post, posted 21 October 2026 at 6:41 pm, opens with the operational line: that day's updates across the entire PHP 8.x line "address two remote code execution holes, and there have been exploits circulating since last night, thanks to a leak in the coordinated disclosure process". Quoting the PHP Foundation, he records that the two CVE IDs began circulating around 15:00 UTC on 20 October with a wrong release time and a wrong CVSS of 10.0 (the real score being 9.2); that the project brought its pre-announcement forward to 19:30 UTC and moved the release from 22 October 14:00 UTC to 21 October 14:00 UTC; and that one of the reporting security firms mistakenly published a proof-of-concept video around 20:00 UTC, which Willison says "contributed to accelerated development of various PoCs" on 21 October. His post names no CVE numbers and no fixed versions.

A post published under the TruFyre name, "PHP2Shell Is a PHP Story. It Is Also an AI Story.", summarises a Wiz Research publication and adds CVE identifiers, fixed versions per PHP branch and an end-of-support date. We do not repeat those numbers here. It is a vendor blog with a sales call to action, it does not mention the leak, and we could not check its figures against the PHP project's own advisory. Take identifiers and fixed versions from the project's advisory, not from a summary. The vendor's AI claim, as relayed there, is that frontier models made the hunt practical for a single researcher in about a week; treat it as the vendor's claim.

The two clocks

In the first story the clock belongs to a status page; in the second, a leak put identifiers and a proof-of-concept video in public before the patch. "Patch first, exploit later" is not a schedule you can plan around.

For a builder on their own VM the useful measure is two intervals: how long your app cannot be deployed when someone else's deploy path stops, and how long it takes to get from "this affects me" to "the fixed version is what my web server executes". Neither reaches zero, both can be known, and the second can be made short.

What a second place to ship needs

  1. A different reason to fail. Another provider, or at least another account and region. Two services on one machine are one failure.
  2. One command from your laptop, not a dashboard click. A script or CI job that pushes the same commit to the second target, reachable while the primary is down.
  3. Secrets, deploy token and DNS account readable without the primary. That, not compute, is the usual blocker.
  4. DNS you can change outside the failing provider, with a TTL short enough to matter.
  5. A decision about state. What cannot move - database, volumes, uploads - and what runs stateless at the second place.
  6. A drill. A second place you have never deployed to is a plan, not a capability: deploy once, time it, note the minutes.

Three checks for your patch state

php -v is the CLI binary, and your web server may be executing a different branch. Ask the package manager and systemd instead:

bash
# what is installed (Debian / Ubuntu, then RHEL family)
dpkg -l | grep -E '^ii +php'
dpkg -s php8.3-fpm | grep -i '^Version'
rpm -qa 'php*'

# which PHP services run, and since when
systemctl list-units --type=service | grep -i php
systemctl status php8.3-fpm

# upgrade, then restart the workers
sudo apt install --only-upgrade php8.3-fpm php8.3-cli
sudo dnf upgrade 'php*'

The line that matters is Active: active (running) since ...: it says whether the workers run the binary you just installed, which a version string does not. Swap 8.3 for your branch; unit names differ between distributions and between mod_php and FPM. In a container, check the image tag and digest and ignore the host.

Is this bulletin about me?

  1. Does it name a component you run, at the level the patch is applied? "PHP" is not "a WordPress plugin": read which layer the advisory says is affected.
  2. Do the fixed versions include your branch? Compare your output above with the versions the PHP project's own advisory lists as fixed.
  3. Is the surface reachable from the internet? Whether exploitation needs authentication changes the urgency; the advisory says which.
  4. Is there a public proof of concept? Willison's post says exploits were circulating before the release, which moves the job from "next maintenance window" to "today".
  5. Who is telling you? A link post, a vendor summary and the project's advisory are three different things. Numbers from the project, chronology from whoever recorded it first.

If the box is yours

Running the app on your own VM changes one thing immediately: nobody else schedules your maintenance window, so the hours in your patch window are yours to spend or lose. It does not remove the dependency, only moves it - to the machine, to whoever rents it to you, and to whoever reads the advisory.

If you are evaluating 2server to run an app and an agent on your own VM, its published requirements say: a VM running Debian 12/13 or Ubuntu 22.04/24.04 with Python 3, key-based SSH and passwordless sudo, and VM memory to start at 2 GB, then sized from each app's replicas and memory, counted twice because a release runs both generations, plus any extensions. Measure on your own box as we measured ours - method here. Nothing here promises that the product patches PHP or any other package for you.

This week: pick the second place and deploy to it once, timed, write the line your agent follows when the primary returns errors, then run the three checks and write down your branch and the version you would need.

Two assumptions broke on one day: that deploy paths stay up, and that patches arrive before exploits do. A second place you have used, and three commands you have run, are the part you control.

Sources: Dennison Bertram, dev.to, Oct 21, Simon Willison, 21 October 2026, TruFyre, PHP2Shell (read on the vendor's blog; the Medium copy did not load for me).