Platform Engineering

PHP runtime upgrades, planned around the application rather than the calendar

On 21 October 2026 the PHP project fixed two critical vulnerabilities that can allow unauthenticated remote code execution. The risk spans PHP installations serving web requests, but the demonstrated pre-application attack is on mod_php; exposure differs by SAPI and configuration. The fixes are in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. We move estates onto a supported branch and verify the application after the switch, on a path that has been rehearsed rather than attempted.

The problem

The runtime is the one dependency nobody chose on purpose

PHP sits underneath the CMS, the framework, the plugins and the theme, which makes it the most consequential dependency in the stack and the least likely to have an owner. It is usually pinned once, during a build or a host migration, and then left alone for years while the branch it was pinned to goes end of life. The scale is the reason this is never one site: PHP is the server-side language on 69.3% of the sites whose language can be identified, and 26.8% of those sites are still on the 7.x line, which has been outside regular PHP project support since PHP 7.4 reached end of life in November 2022 (W3Techs, read 24 October 2026). One-off source or vendor backports may still be available. Advisories are published against the engine rather than against the application on top of it, so a site whose own code is flawless inherits engine flaws through request handling alone — and the reason that becomes expensive is not the patch. It is that most estates cannot say which versions, which SAPIs and which configurations they are actually serving, so the first task is always enumeration.

  • Production runs a branch the PHP project no longer supports
  • An advisory names the runtime and nobody can list the versions the estate serves
  • A host, control panel or vendor has said the branch is end of life
  • A previous upgrade was rolled back after something broke in production
  • Deprecation warnings are filtered out of the logs rather than dealt with
  • The application's stated requirement and the installed runtime disagree
  • Several SAPIs, pools or hosts across the estate, each configured differently
  • Nobody can say which extensions are loaded, or which plugin needs them
  • The upgrade is waiting on a platform release that is itself waiting on the runtime
Who this is for

The people who usually bring us this problem

An operations or platform lead who has inherited the estate

You need to know what is actually running before you can decide anything, and the person who knew has left. The inventory is useful on its own, and it is the artifact every later decision refers back to.

An agency or host holding several sites on an old branch

The same runtime is behind more than one site, and the upgrade has to be planned as a repeatable procedure rather than improvised per site. The inventory covers the estate; the procedure covers the next site.

Someone who has just read a security notice

The complete fix is an update, and the question is how to apply it without breaking a site that is currently working. Where the update cannot happen this week, the advisory's configuration measures reduce exposure in the meantime, and the page is explicit about what they do and do not cover.

A team planning a platform upgrade

The CMS or forum release you want may require a runtime you do not have, and the platform upgrade may require code changes that the runtime change also requires. Sequencing them badly means doing the work twice.

What it costs

What this costs while it goes unfixed

Engineering faults are rarely confined to the engineering layer. These are the commercial consequences we see most often.

An unsupported branch is not patched at all

After end of life, a branch no longer receives regular fixes from the PHP project, and the deferred upgrade becomes the lasting remedy. One-off source backports or fixes from a distribution or long-term support vendor may exist, so check the specific package rather than assuming either way. PHP 8.1 reached end of life on 31 December 2025, so this is the current position for every site still running it rather than a future risk.

Engine flaws do not care how careful the application is

The October 2026 vulnerabilities are reached through request parsing, which happens before the application runs. Nothing in the site's own code, framework or plugin audit changes that, and no amount of application hardening compensates for a runtime that is three branches behind.

The gap widens in both directions

Deprecations accumulate in the application while the runtime moves on underneath it. Each branch skipped adds compatibility work and removes community experience with that particular path, which is why long-deferred upgrades are usually applied as a sequence of smaller jumps rather than as one change.

An upgrade that fails in production fails publicly

Runtime faults are not subtle: a version mismatch typically produces a blank page or a fatal error rather than a degraded one. The cost is measured in the traffic that arrives during the window, and in whatever the search engines make of a site that served errors for an afternoon.

Some hosts retire old branches on their own schedule

Where the runtime is not yours to choose, the deadline is somebody else's, and it can arrive with less notice than a planned upgrade would have needed. That is a reason to move the branch before the host does rather than after.

What we do about it

Capabilities

Each of these is work we carry out, not an area we advise on.

Estate inventory

Every runtime the estate actually serves: version per host, pool and vhost, the SAPI in front of it, the configuration in force, and the extensions loaded with the ones the application genuinely requires. It is unglamorous work and it is the prerequisite — an advisory naming versions cannot be answered without it.

Compatibility analysis before anything changes

Deprecations and removals between the current branch and the target, extension availability per branch, framework and platform version requirements, and the plugin inventory that decides what actually breaks. The output names the blocking items rather than describing the risk of them.

A target chosen deliberately

A supported branch rather than the newest one, bounded by what the application supports and what its vendors support. Where the platform upgrade needs a newer runtime than the site can currently run, the sequencing is planned, because the two changes interact and doing them in the wrong order does the work twice.

Rehearsal on a copy of the real thing

The upgrade applied to a replica or a canary carrying the real application, the real plugins and real data — not a clean install, which passes for reasons that do not survive contact with production. Where a step cannot be rehearsed, that is stated before the window rather than discovered during it.

Per-SAPI posture

mod_php, PHP-FPM, FrankenPHP, LSAPI and CGI have different exposure under these flaws. PHP identifies all PHP installations serving web requests as at risk, with the highest risk on mod_php, where a demonstrated attack can trigger before application code runs. Pool and worker behaviour, configuration and where the runtime actually lives are part of the assessment.

Configuration posture for the window

The measures the advisory names — an administratively enforced memory limit, conservative request-size limits enforced at the proxy as well as in PHP, upload progress disabled, workers restarted so the settings actually apply. Applied as exposure reduction while the update is scheduled, and described as exactly that: the advisory is explicit that configuration removes specific paths and that updating is the only complete mitigation.

A rollback that has been executed once

Both runtimes installed and selectable, so the branch can be switched per pool or vhost rather than only by re-deploying. A rollback that has never been run is a plan, not a control, so it is exercised before the window rather than during it.

Verification after the switch

Error rate, the deprecation log, the functional paths that carry traffic, request latency and caching behaviour, read after the change rather than assumed from a successful deploy. The check confirms which runtime is serving the request, because a site can pass every functional test while still being served by the version that was supposed to have been replaced.

Visibility afterwards, so the next advisory is a query

The estate's runtime versions recorded where they can be looked up, and a maintenance calendar keyed to the project's own support dates. Without that, the next advisory produces the same investigation as this one, and the estate drifts back out of support between incidents.

How we work

Engineering methodology

The sequence is deliberate. The order is usually what determines whether the work holds or has to be repeated.

  1. Enumerate before touching anything

    An estate that has never been inventoried has an unknown number of runtimes in it, and the first upgrade applied to a guessed inventory is a lesson in how many were actually there. The inventory is also the document that makes the rest of the work auditable.

  2. Choose the branch, then the patch level

    These are two different changes and they carry different risk. Applying the current security release within the branch a site already runs is usually a small, contained change. Moving branch is a project with compatibility work, and it is the only answer to end of life. Saying which one is being done, and why, is part of the plan.

  3. Rehearse against the application, not against PHP

    A clean runtime install proves the runtime works. The failures that matter come from the application — a deprecated call reached on one template, an extension loaded by a plugin, a caching layer keyed to the runtime version — and they appear on a copy of the real site or they appear in production.

  4. Change one variable at a time

    Runtime, then application code, then configuration, in that order and with a verification between each. Bundling them means a fault cannot be attributed, and an unattributed fault is usually resolved by reverting all three.

  5. Verify on the serving path

    A deploy that reports success has reported that files were written. The evidence that matters is a request served by the new runtime, with the application's own logs and the response times read afterwards. Anything less is a statement about the deployment rather than about the site.

  6. Keep the answer to the next advisory

    The version list, the support dates and the procedure are kept current, so the next disclosure is answered from a document instead of from a rebuild of this investigation. An estate that cannot answer "which versions are we running" quickly is one that pays for the same discovery repeatedly.

Deliverables

What an engagement produces

Documentation is a deliverable, not an afterthought. On most of these engagements a large part of the value is a defect report precise enough for another team to act on.

Inventory

  • Every runtime the estate serves, by host, pool and vhost, with its exact version
  • The SAPI in front of each one, and where its configuration lives
  • Extensions loaded, with the ones the application actually depends on
  • Which branches are in support, and the date each one stops receiving security fixes
  • Anything that could not be determined, stated as unknown rather than assumed

The upgrade

  • A target branch and patch level, with the reason for choosing them
  • A compatibility report naming the code, extension and platform items that block it
  • The sequence, with the windows each step needs and what each step touches
  • A rollback procedure that has been executed on the rehearsal copy
  • The interim configuration posture, in force from the day it is agreed

Afterwards

  • A verification record: what was checked, on which paths, and what it showed
  • Confirmation of which runtime is actually serving production traffic
  • The estate's runtime versions recorded where they can be looked up
  • A maintenance calendar keyed to the project's published support dates
  • The triage arrangement for critical PHP security releases, in writing
Under the hood

Architecture and technology

The two flaws of 21 October 2026, in a paragraph each

  • CVE-2026-109618 — memory exhaustion during request handling. PHP aborts an out-of-memory condition by jumping out of the current context, and some contexts do not account for that exit: request memory is left only partially initialised, and the request-cleanup procedure may read or branch on it. Several multipart parsing strategies reach that state from a request that looks ordinary — a body without a usable declared length, an unrestricted number of part headers, or empty file controls that are not counted against the upload limit.
  • CVE-2026-109619 — request state that outlives its memory. Global state that points into request memory is not always reset between requests, or is repopulated after being reset, so a later request handled by the same worker can read that stale state before normal initialisation replaces it. The advisory is careful about scope here: the patch closes the confirmed routes rather than every variant of the pattern.
  • Why the SAPI is part of the answer. The PHP project says all installations serving web requests are at risk and identifies mod_php as the highest risk, with a demonstrated unauthenticated attack before application code runs. Exposure on PHP-FPM and other SAPIs depends on the request path, worker behaviour and configuration; do not treat one SAPI's demonstration as proof that every deployment is exploitable in the same way.
  • Why the fix is an update. The patch replaces the out-of-memory jump with a delayed soft failure at the next safe point in the VM and a hard exit above a second, higher threshold, which is what stops request cleanup from ever seeing invalid state. The advisory states plainly that updating is the only complete mitigation, and that the configuration measures described below remove specific attack paths rather than the pattern.

What the configuration measures actually change

  • An administratively enforced memory limit. Setting memory_limit=-1 removes the controllable PHP memory-limit failure path, but an underlying allocation failure can still reach vulnerable code, so this reduces exposure rather than closing it. Apply it where the application cannot raise it. It also removes PHP's own ceiling on a runaway request, which is why the advisory pairs it with a container or cgroup limit as the availability boundary and warns against RLIMIT_AS or RLIMIT_DATA.
  • Request size and shape limits. A conservative post_max_size, an independent decoded-size limit at the proxy or edge, and bounds on header counts, multipart parts and nesting depth. These reduce the deterministic path and ordinary denial-of-service exposure at the same time, and they have to cover requests that arrive without a usable Content-Length.
  • Upload progress, backtraces and diagnostics. Disabling session upload progress and restarting every worker closes the confirmed session path, and on PHP 8.5 disabling fatal-error backtraces closes another. Suppressing the underlying diagnostics with error_reporting, display_errors or the silence operator does not help: the diagnostic itself is what reaches the vulnerable path, so the fatal error has to be fixed rather than hidden.
  • Follow-up advisory, 23 October 2026. PHP recommended setting session.upload_progress.enabled=0 until the next regular bug-fix release to address CVE-2026-115560. PHP says this additional RCE vector requires an unusual combination: session.serialize_handler is configured as php_binary or php_serialize, the application switches it to php with ini_set() before session_start(), and upload progress remains enabled. Keep the mitigation in server or pool configuration and restart workers; do not assume an application-level ini_set() is early enough.

Posture applied during an upgrade window, taken from the advisory's own mitigation list. It belongs in the pool or server configuration rather than in the application, because a value fixed there cannot be raised from inside a request — and it has to be in force before request parsing begins, which is earlier than any application code runs.

; FPM pool: values the application cannot override at runtime
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 30M
php_admin_flag[session.upload_progress.enabled] = off

The advisory names an enforced memory_limit of -1 as the primary configuration mitigation for the memory-exhaustion flaw, and is equally clear that it is not a complete one. It removes PHP's own limit on a runaway request, which is why the same advisory pairs it with a container or cgroup limit as the availability boundary, and why it is a measure for a window rather than a configuration to leave in place indefinitely.

Related work

Where we have done this

Engagements where this capability was the substance of the work rather than a line item.

Online communities

Spain's largest forum

Since 2019, Soludome has managed infrastructure and platform operations for one of Spain's largest online communities. The work covers server and performance optimisation, CDN architecture, load balancing and site security under sustained traffic.

Since 2019continuous engagement
Online communities

Arrse.co.uk

An established community platform had accumulated three separate problems that compounded each other: page loads that had degraded with growth, search visibility that had not kept pace with the community's authority, and a security posture that had not been revisited as the platform's profile grew. The engagement addressed all three concurrently.

4%increase in organic clicks
Online communities & specialist publishing

GuzziTech & RideMalibu

Since 2021, Soludome has managed infrastructure, site performance and technical SEO across GuzziTech and RideMalibu as a connected web estate. The engagement includes dedicated infrastructure and continuing operational ownership.

Since 2021managed infrastructure, performance and SEO
Adjacent problems

If this is not quite your problem

These overlap at the edges. Sending you to the right page is more useful than having you work it out.

The code will not run on a supported branch

The other half of the same problem, and the one an engine update cannot touch: functions a supported branch removed, deprecated syntax, extension surfaces that moved, and components nobody maintains. It is a codebase change rather than a configuration one, and the two are usually sequenced together.

Legacy PHP modernisation

The server underneath the runtime is the problem

Capacity, process management, database and OS-level maintenance are a different engagement from the runtime version, even though both end up in the same configuration files.

Server management

You suspect the site is already compromised

An unpatched engine is a way in, and a site that shows symptoms has moved past the point where an upgrade is the first step. Containment, scope and recovery come first, and the upgrade follows.

Hacked website recovery

You want the application's own attack surface reduced

Hardening is the application layer: authentication, file permissions, plugin surface, update policy. It is worth doing and it does not compensate for an unsupported runtime, which is why it is a separate page.

WordPress security hardening

The platform upgrade is the change you are really planning

A CMS or forum release usually brings its own version requirements and its own code changes. Where the platform move is the goal, that page sequences it; this one deals with the runtime the platform sits on.

XenForo installation and upgrade

You need the estate kept current rather than upgraded once

The upgrade is a project with an end. Keeping a runtime and its applications patched afterwards is a cadence, with an owner and a record of what was applied.

Website security maintenance
Client proof

What Clients Say; And Where To Verify It

Our client reviews are published on our public Google Business Profile. We reproduce them verbatim, with attribution, so you can read the original feedback and verify it directly at the source. We believe reviews should speak for themselves.

5.05 out of 5 stars15 Google reviewsReviews are hosted on our Google Business Profile.
  • 5 out of 5 stars

    We reached out to this company when our website was hacked, and we are incredibly grateful for their prompt assistance in securing our project. They also provide regular, timely updates and invaluable support with other aspects of our platform.

    Swood
  • 5 out of 5 stars

    Excellent work! They patiently accommodated all my requests and offered fair pricing. Highly recommended.

    Nico

Read all client reviews

Questions

Frequently asked

Which PHP versions are affected by the vulnerabilities disclosed on 21 October 2026?

The two engine vulnerabilities — CVE-2026-109618 and CVE-2026-109619 — were fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP identifies installations serving web requests across PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed as at risk, while naming mod_php as the highest risk because an unauthenticated attack was demonstrated before application code runs. For PHP 8.1 and older, check whether your distribution or long-term support vendor has backported a fix; otherwise, move to a supported branch.

Is PHP 8.1 still supported?

No. PHP 8.1 reached end of life on 31 December 2025 and no longer receives regular fixes from the PHP project. A distribution or long-term support vendor may provide a backport for a specific vulnerability, so check the package you run; do not assume every vulnerability is fixed or that a backport is available. The branches in support are 8.2, 8.3, 8.4 and 8.5, and each leaves security support on a published date: 8.2 on 31 December 2026, 8.3 on 31 December 2027, 8.4 on 31 December 2028 and 8.5 on 31 December 2029. A branch being supported today is not a permanent state, which is the reason the maintenance calendar is part of the deliverable.

Can we apply the security patch without changing branch?

Yes, and for many estates that is the correct change: moving from one patch level to the current release within the same branch is a small, contained update with a good track record. Moving branch is a different and larger project, because it changes deprecations, extension availability and platform compatibility at the same time. We will say which one a situation actually needs rather than treating every case as the larger job. What is not a choice is staying on a branch that no longer receives fixes.

What usually breaks in a PHP upgrade?

The failures cluster. Code written for an older branch hits deprecations that have since become errors, or functions that have been removed or renamed. Plugins and extensions turn out to require a specific branch even though the platform does not. Some sites carry warnings that have been suppressed for years, and the upgrade stops suppressing them — which is a fix being applied, not a regression. Less obviously, a caching layer or opcache configuration keyed to the runtime version can behave differently after the switch, which is why verification reads the application's own logs and response times rather than only checking that pages load.

Can it be done without downtime?

Usually with very short windows rather than none at all, and the sequence is arranged to keep them to a minimum. Both runtimes stay installed and selectable per pool or vhost during the change, so the switch is a configuration change rather than a redeploy, and the rollback is the same operation in reverse. Steps that genuinely require the application to be quiet — a migration whose schema depends on the runtime, for instance — are identified in the plan with the window they need, rather than being discovered on the night.

What if we do not control the runtime?

On shared hosting or a managed platform you may have no shell and no direct control of the branch, and that changes the work rather than preventing it. What can be established is which version is serving the site, which branch it is on, whether the plan around it will move and when. Where the answer is that it will not move, the honest recommendation is to move the site — and the useful thing is to know that before the branch reaches end of life rather than afterwards.

How quickly do you respond to a PHP security release?

For estates we operate under a maintenance arrangement, critical PHP security releases are triaged the same business day: we establish whether the estate is exposed, which branches and SAPIs are affected, and whether the mitigation posture needs to change ahead of the update. That is the commitment, and it is the only one on this page. No timeframe is claimed for an upgrade itself, because a branch move's duration depends on what the compatibility analysis finds, and we would rather tell you that after looking than before.

Bring us the problem you have not been able to fix

Describe what is happening rather than what you think the cause is. If we are not the right people for it, we will say so.