maborak.com~/blog/cve-2026-115560-php-session-serializationsoftware & infrastructure engineering
Back to all articles

CVE-2026-115560: audit PHP session serialization changes

The configuration and application-code conditions behind PHP's October 23 session advisory, with a source audit, mitigation placement and regression plan.

By the Maborak engineering team · · 6 min read

CVE-2026-115560 needs a separate check after the October 21 PHP updates. Its disclosed condition involves both server configuration and an application changing the session serializer. A version-only inventory cannot answer whether that combination exists.

Status checked 29 October 2026: PHP’s October 23 informational notice remains the basis for this article. It says the full advisory will accompany a regular release. We do not assign a speculative CVSS score, claim a new fixed version or invent a memory-corruption sequence that the notice does not disclose. The review and regression procedure below is our recommendation, not a claim that we reproduced the vulnerability.

The disclosed combination

PHP identifies this combination: upload progress enabled; session.serialize_handler initially configured as php_binary or php_serialize; application code switching it to php using ini_set() before session_start(). PHP recommends session.upload_progress.enabled=0 pending the next regular bugfix release, and says applications that never change serializer at runtime can leave the feature enabled. The notice does not establish a complete affected-version matrix. PHP informational advisory.

That is a conjunction, not a list of independent vulnerabilities. Finding php_serialize alone is not enough. Finding session_start() alone is not enough. A useful assessment must establish the initial setting, the executed code path and the order in which it changes that setting.

Use three explicit outcomes in the review:

Evidence Assessment for the disclosed condition
All listed conditions established Apply the mitigation and track the vendor fix
At least one required condition demonstrably absent Document which condition is absent
Configuration or execution order unknown Review incomplete; do not label unaffected

This classification is intentionally narrower than “all PHP vulnerabilities resolved.” The earlier stale-state issue still requires its patched runtime.

Serializer and storage handler are different settings

PHP’s session configuration distinguishes the save handler from the serialization handler. session.save_handler selects storage behavior; session.serialize_handler selects the encoding and decoding format. PHP lists php, php_binary and php_serialize among its built-in formats. session.upload_progress.enabled defaults to enabled and is an INI_PERDIR directive. PHP session configuration reference.

This matters during a migration review. Moving sessions to a different storage service does not, by itself, document which serializer the application uses. Likewise, a consistent serializer in one application does not establish consistency across all applications sharing a deployment template.

Our recommended configuration record has separate fields for storage handler, storage destination, serializer at startup, serializer before session start, and upload-progress setting. Keep credentials and actual session contents out of that record. The goal is to establish behavior, not copy sensitive state into a ticket.

Why upload progress belongs in the review

PHP’s upload-progress mechanism records progress in session data while an upload is being processed. It is triggered through the configured upload-progress form field, and the manual describes a separate request polling the progress information. The manual also cautions that some web servers buffer a request before PHP receives it, affecting when progress can be observed. PHP upload-progress documentation.

For an operator, the practical consequence is to test the actual request path. An upload form that appears to work through one proxy does not prove that every route uses the same buffering, runtime or session configuration. Trace the route from the browser-facing endpoint to the application pool before deciding that a feature is unused.

The public informational notice is not enough to reconstruct the vulnerable internal decoder path. It would be misleading to publish a guessed pointer lifetime, heap layout or exploit chain as a fact. The disclosed prerequisite is sufficient to perform a configuration-and-code review while the fuller technical material is pending.

Search the application and deployment sources

Start with a broad source search rather than a fragile expression intended to identify only exact function calls:

rg -n --glob '*.php' 'session\.serialize_handler|session_start|ini_set' src app
rg -n 'session\.serialize_handler|session\.upload_progress\.enabled' config deploy
rg -n 'auto_prepend_file|session\.auto_start' config deploy

Replace these directories with the paths used by the application. Include generated configuration, bootstrap files and relevant dependencies in a second pass. A vendor directory can contain the code that actually starts the session, even when the application’s own code contains no direct call.

For every match that changes the serializer, answer four questions:

  1. What value is effective before application bootstrap?
  2. Which conditional branch changes it, and to what value?
  3. Does that branch execute before the first session start?
  4. Can an HTTP request reach that branch in the deployed application?

Literal search will not identify a setting assembled from strings or hidden behind a configuration wrapper. Follow the wrapper to its implementation. Equally, a test fixture or an unreachable compatibility branch should not be reported as an active production path without evidence.

The following is a review example, not a reproduction. It shows the application-side ordering that deserves attention if the initial configuration supplies one of the serializers named in the advisory:

<?php
// Review this pattern against the startup configuration.
ini_set('session.serialize_handler', 'php');
session_start();

Do not “fix” the finding by changing the deployment’s serializer at random. That could create a separate compatibility problem with existing session data. First establish why the override exists and which applications share the session store.

Put the mitigation in the serving configuration

For a deployment using a shared INI file loaded before requests:

session.upload_progress.enabled = 0

For an existing FPM pool, use the administrative equivalent:

php_admin_flag[session.upload_progress.enabled] = off

FPM documents the pool configuration syntax and administrative overrides. Make the change in the actual pool serving the affected application. FPM configuration manual.

The earlier PHP deployment notice explicitly requires pre-parsing configuration and worker replacement for the upload-progress control. An application-level setting applied after input processing is not an equivalent control.

Our verification procedure is to read the effective value from an access-restricted operational route in the serving pool, replace the relevant workers, and repeat that observation. Check every replica. Keep the package update for the October 21 vulnerabilities in place while evaluating this later advisory; the session control and runtime update cover different findings.

Regression tests for the change

Use ordinary application requests in staging. The regression suite should distinguish the file-transfer result from any progress UI:

  • Upload a representative valid file and verify the saved object or record.
  • Exercise a normal validation failure and confirm the application reports it correctly.
  • Observe whether the progress indicator depends on PHP session progress or a different mechanism.
  • Check login, logout and session continuity across more than one request.
  • Exercise two relevant application routes that share session storage.
  • Repeat against each distinct pool or runtime configuration.

These tests establish whether the mitigation breaks expected behavior. They are not an exploit test and cannot establish a universal absence of memory-safety defects.

If removing a runtime serializer change is part of the longer-term repair, plan a session-format migration separately. Decide how to handle existing sessions, whether users must sign in again, which applications must change together and how rollback would work. Avoid a rolling change that silently leaves different nodes interpreting the same stored sessions under inconsistent assumptions.

Evidence needed to close the review

Keep a dated copy or link to the vendor guidance, the configuration revision, the relevant code path, the effective values observed from the serving runtime and the regression results. If the disclosed combination is absent, state exactly why. “No matching text found” is weaker evidence than a traced bootstrap sequence and confirmed startup configuration.

When PHP publishes the full advisory and fixed releases, reassess the finding against those details. Until then, record the mitigation as a configuration control and retain the open dependency on the vendor release. That gives the next engineer an exact reason for the setting and a clear condition for reviewing it later.

Back to all articles

Technologies we work with

  • Argo CD
  • Kubernetes
  • Docker
  • Podman
  • Ansible
  • Jenkins
  • Chef
  • Proxmox VE
  • Google Cloud
  • Linux
  • Red Hat
  • CentOS
  • NGINX
  • Apache
  • Traefik
  • Prometheus
  • Grafana
  • PostgreSQL
  • MySQL
  • MariaDB
  • Redis
  • etcd
  • Qdrant
  • Elasticsearch
  • Logstash
  • Kibana
  • PagerDuty
  • Go
  • Python
  • FastAPI
  • PHP
  • TypeScript
  • React