# CVE-2026-109619 — PHP : exécution de code

- Link: https://dpioch.aristeecampus.org/veille/veille-v2-27859b91401d560160cf1cf1/
- Published: 2026-10-23T20:28:00+02:00
- Author: Admin

CVE-2026-109619 permet une divulgation de mémoire et une exécution de code à distance
sans authentification, avec les privilèges du worker web. L'exécution de code est
confirmée sur mod_php et, pour le cycle de vie des sessions, sur FPM. Le défaut 
provient d'états globaux conservés par un worker alors que la mémoire de la requête
correspondante a été libérée. Une opération précédant l'initialisation normale de
la requête suivante réutilise ces références périmées : c'est une utilisation après
libération. La correction est urgente au regard des preuves de concept connues du
CERT-FR pour certains déploiements PHP. Cette information ne constitue pas une confirmation
d'exploitation en conditions réelles. Pour les branches maintenues décrites par 
PHP, les versions affectées sont les 8.2.x antérieures à 8.2.35, 8.3.x antérieures
à 8.3.36, 8.4.x antérieures à 8.4.27 et 8.5.x antérieures à 8.5.12.

Tri IA initial, TL;DR français sourcé et revue séparée ; champs absents : inconnu.

Composant : PHP

Versions : [{"lessThan": "8.2.35", "status": "affected", "version": "8.2.*", "versionType":"
semver"}, {"lessThan": "8.3.36", "status": "affected", "version": "8.3.*", "versionType":"
semver"}, {"lessThan": "8.4.27", "status": "affected", "version": "8.4.*", "versionType":"
semver"}, {"lessThan": "8.5.12", "status": "affected", "version": "8.5.*", "versionType":"
semver"}]

Priorité éditoriale : critique

CVE : CVE-2026-109619

Date source : 2026-10-21T13:34:13Z

## Référence — titre original

RCE via stale global state

## Citation originale (en, non traduite)

> PHP contains various global state, such as error, session, object and extension
> state that is retained by a worker but points to memory owned by one request. 
> That state must be reset before the request memory is released. Some input, configuration,
> session and error handling operations run before normal initialization of the 
> next request. They inadvertently access stale state not reset by the previous 
> request before initialization has a chance to replace it, causing a use after 
> free. A strategically crafted heap layout can produce full remote code execution(
> RCE).
> State can survive for more than one reason. A fatal error, including one caused
> by memory exhaustion, can abandon an operation before it performs its matching
> reset. A warning or other nonfatal diagnostic can also repopulate error state 
> after that state was already cleared during shutdown. The request heap is then
> freed while the worker global field still refers to it. A later operation that
> runs before normal request initialization can consume the stale value.
> Successful exploitation of this vulnerability requires both a producer and a consumer.
> The producer is a PHP operation that stores state owned by one request in a location
> PHP can access later in a subsequent request. The consumer is a subsequent PHP
> operation that reads, frees, branches or otherwise acts on the stale state previously
> stored by the producer.
> A concrete vulnerability would arise under the following conditions:
> 1. A reachable PHP operation stores request-owned state in a globally accessible
> location, acting as the producer.
>  2. The state is not reset, or another operation
> repopulates it after its normal reset. 3. PHP releases the request memory while
> the persistent worker retains the referring global state. 4. The same worker handles
> another request. 5. A PHP operation reads, frees, branches or otherwise acts on
> the stale state before normal request initialization resets it, acting as the 
> consumer.
> The demonstrated producing and consuming operations occur in different HTTP requests
> handled by the same worker. The exact affected versions, configuration and mitigations
> depend on the internal state affected by the producing operation.

Avis de l’éditeur : inconnu sauf référence explicitement acquise.

[Source acquise](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

## Priorité critique — analyse et éléments sourcés

## Résumé opérationnel (TL;DR)

CVE-2026-109619 permet une divulgation de mémoire et une exécution de code à distance
sans authentification, avec les privilèges du worker web. L'exécution de code est
confirmée sur mod_php et, pour le cycle de vie des sessions, sur FPM.

> The confirmed impact is unauthenticated heap use-after-free, memory disclosure
> and remote code execution with the web worker's privileges. The fatal backtrace
> path has confirmed RCE against mod_php. Session lifecycle RCE was validated against
> mod_php and FPM.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

Le défaut provient d'états globaux conservés par un worker alors que la mémoire 
de la requête correspondante a été libérée. Une opération précédant l'initialisation
normale de la requête suivante réutilise ces références périmées : c'est une utilisation
après libération.

> PHP contains various global state, such as error, session, object and extension
> state that is retained by a worker but points to memory owned by one request. 
> That state must be reset before the request memory is released. Some input, configuration,
> session and error handling operations run before normal initialization of the 
> next request. They inadvertently access stale state not reset by the previous 
> request before initialization has a chance to replace it, causing a use after 
> free.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

La correction est urgente au regard des preuves de concept connues du CERT-FR pour
certains déploiements PHP. Cette information ne constitue pas une confirmation d'exploitation
en conditions réelles.

> Le CERT-FR a connaissance de preuves de concept pour les vulnérabilités CVE-2026-
> 109618 et CVE-2026-109619 pour des déploiements spécifique de PHP.

[Source de cet élément](https://www.cert.ssi.gouv.fr/alerte/CERTFR-2026-ALE-014/)

Pour les branches maintenues décrites par PHP, les versions affectées sont les 8.2.
x antérieures à 8.2.35, 8.3.x antérieures à 8.3.36, 8.4.x antérieures à 8.4.27 et
8.5.x antérieures à 8.5.12.

> "affected_versions": [{"lessThan": "8.2.35", "status": "affected", "version": "
> 8.2.*", "versionType": "semver"}, {"lessThan": "8.3.36", "status": "affected","
> version": "8.3.*", "versionType": "semver"}, {"lessThan": "8.4.27", "status": "
> affected", "version": "8.4.*", "versionType": "semver"}, {"lessThan": "8.5.12","
> status": "affected", "version": "8.5.*", "versionType": "semver"}]

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

## Impact

L'évaluation CVSS 4.0 fournie est critique, à 9.2 : attaque réseau sans privilèges
ni interaction utilisateur, mais avec complexité élevée et conditions supplémentaires
nécessaires. Les impacts sur la confidentialité, l'intégrité et la disponibilité
du système vulnérable sont élevés.

> {"Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "Safety": "NOT_DEFINED","
> attackComplexity": "HIGH", "attackRequirements": "PRESENT", "attackVector": "NETWORK","
> baseScore": 9.2, "baseSeverity": "CRITICAL", "exploitMaturity": "NOT_DEFINED","
> privilegesRequired": "NONE", "providerUrgency": "NOT_DEFINED", "subAvailabilityImpact":"
> NONE", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "userInteraction":"
> NONE", "valueDensity": "NOT_DEFINED", "vectorString": "CVSS:4.0/AV:N/AC:H/AT:P/
> PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N", "version": "4.0", "vulnAvailabilityImpact":"
> HIGH", "vulnConfidentialityImpact": "HIGH", "vulnIntegrityImpact": "HIGH", "vulnerabilityResponseEffort":"
> NOT_DEFINED"}

[Source de cet élément](https://cveawg.mitre.org/api/cve/CVE-2026-109619)

La mise à jour contenant la réinitialisation complète des états est la seule atténuation
fiable selon PHP. Aucun réglage générique ne couvre tous les chemins applicatifs,
d'extensions ou de serveur concernés.

> Updating to a release containing the complete state reset patch is the only reliable
> mitigation. **There is no complete generic configuration mitigation as an application,
> extension or server path may publish stale state or consume it without a predictable
> log entry.**

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

## Mécanisme et prérequis

Une erreur fatale, notamment un épuisement mémoire, peut empêcher la remise à zéro
d'un état. Un diagnostic non fatal émis tardivement pendant l'arrêt peut aussi recréer
cet état après son nettoyage.

> State can survive for more than one reason. A fatal error, including one caused
> by memory exhaustion, can abandon an operation before it performs its matching
> reset. A warning or other nonfatal diagnostic can also repopulate error state 
> after that state was already cleared during shutdown.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

L'exploitation exige que les requêtes productrice et consommatrice atteignent le
même worker. Multiplier ou recycler les workers réduit la réussite par requête, 
sans supprimer la condition vulnérable.

> The producer and consumer requests must reach the same worker. Multiple workers
> and recycling reduce success per request but do not remove the condition.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

Deux voies précoces sont décrites : les diagnostics de configuration INI et le suivi
de progression des téléversements. Ce dernier est activé par défaut et ne nécessite
aucun appel applicatif à session_start().

> Session upload progress can reach session handling before ordinary session initialization.
> It can therefore consume session or decoder state left by an interrupted request
> before normal initialization resets it. This consumer is independent of the INI
> diagnostic path and does not require a diagnostic from configuration.
> ## Concrete and candidate cases
> ### PHP 8.5 fatal error backtrace: confirmed
> With `fatal_error_backtraces` enabled, fatal error reporting stores backtrace 
> state owned by the request. Resetting of this global state is always missed during
> shutdown. A diagnostic on a subsequent request reaches the stale value before 
> normal request initialization resets it.
> This is the strongest demonstrated case and is the basis of the confirmed mod_php
> exploitation.
> ### Session upload progress lifecycle: confirmed
> An upload can initialize request-owned session and decoding state before normal
> module initialization. OOM or another fatal error after that state has been published
> can prevent its matching reset. PHP then frees the request heap while persistent
> session or decoder globals still refer to it. A later upload progress operation
> reaches those globals before ordinary initialization and treats them as valid 
> state.
> The demonstrated application-independent trigger is OOM during input processing.
> Other fatal errors at this stage can cause the same state transition, but generally
> require additional application, extension or configuration conditions.
> With mod_php, both the producing operation and fatal error can occur during multipart
> startup. FPM terminates a child when this startup fails, so that exact sequence
> does not survive. The validated FPM path instead publishes state during application
> execution after successful startup, reaches a fatal error, and then uses session
> upload progress as the early consumer. It works with a normal dynamic FPM pool,
> although it depends on a suitable application operation.
> Session upload progress is enabled by default, and no application call to `session_start()`
> is required.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

Pour le chemin session validé sous FPM, l'état périmé est produit pendant l'exécution
applicative après un démarrage réussi : l'exposition dépend donc d'une opération
applicative appropriée, contrairement au scénario multipart précoce décrit pour 
mod_php.

> With mod_php, both the producing operation and fatal error can occur during multipart
> startup. FPM terminates a child when this startup fails, so that exact sequence
> does not survive. The validated FPM path instead publishes state during application
> execution after successful startup, reaches a fatal error, and then uses session
> upload progress as the early consumer. It works with a normal dynamic FPM pool,
> although it depends on a suitable application operation.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

Masquer ou désactiver l'affichage et la journalisation des erreurs ne protège pas:
l'état global est consulté avant la décision de signaler le diagnostic.

> Global state is accessed before PHP decides whether to report, display or log 
> the warning. Changing `error_reporting`, using `@`, or disabling `display_errors`
> or `log_errors` does not protect against this vulnerability.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

## Indicateurs publiés par l’éditeur

Non établi par les sources acquises.

## Mesures documentées

Updating to a release containing the complete state reset patch is the only reliable
mitigation.

> Updating to a release containing the complete state reset patch is the only reliable
> mitigation.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

For PHP 8.5 installations that cannot update, set `fatal_error_backtraces=0` administratively
and restart every worker. This removes the producer used by the confirmed RCE case.
It does not cover other request-owned global or extension state.

> For PHP 8.5 installations that cannot update, set `fatal_error_backtraces=0` administratively
> and restart every worker. This removes the producer used by the confirmed RCE 
> case. It does not cover other request-owned global or extension state.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

For the session lifecycle case, set `session.upload_progress.enabled=0` administratively
and restart every worker. This prevents the demonstrated early session producing
and consuming operations. It does not mitigate the other lifecycle paths.

> For the session lifecycle case, set `session.upload_progress.enabled=0` administratively
> and restart every worker. This prevents the demonstrated early session producing
> and consuming operations. It does not mitigate the other lifecycle paths.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

Logs must supplement a static configuration and application flow audit.

> Logs must supplement a static configuration and application flow audit.

[Source de cet élément](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)

Aucune annexe présentée comme intégrale : consulter l’avis officiel lié.

Attribution : avis officiel de l’éditeur, sans corroboration indépendante alléguée.
La date d’ajout au catalogue KEV n’est pas une date de divulgation. Les échéances
CISA affichées ne constituent pas des obligations universelles.

## Correctifs et versions — texte original de l’éditeur, non traduit

    ```
    > [!WARNING]
    > Updating to a release containing the complete state reset patch is the only reliable mitigation. **There is no complete generic configuration mitigation as an application, extension or server path may publish stale state or consume it without a predictable log entry.**

    For PHP 8.5 installations that cannot update, set `fatal_error_backtraces=0` administratively and restart every worker. This removes the producer used by the confirmed RCE case. It does not cover other request-owned global or extension state.

    For the session lifecycle case, set `session.upload_progress.enabled=0` administratively and restart every worker. This prevents the demonstrated early session producing and consuming operations. It does not mitigate the other lifecycle paths. It might be prudent to set `session.upload_progress.enabled=0` if you don't need this feature even after applying the patch, as more attackers try to find flaws in this hardly-used and hardly-tested feature.

    Reduce the remaining risk by breaking as many links in the lifecycle as possible:

    1. Eliminate fatal errors on paths reachable by an attacker. Include failures that depend on request flow in upload, import, error page, shutdown, destructor, serialization, output handler, plugin and extension paths rather than only failures seen during ordinary page requests.
    2. Eliminate warnings and other diagnostics emitted during extension post-deactivation and server cleanup, after normal request error state has already been cleared.
    3. Eliminate diagnostics from all INI configuration applied before request initialization. Prefer `php.ini`, FPM pool or server configuration applied at startup over per request overrides, and remove obsolete directives.
    4. If performance is not a factor, consider limiting the number of requests a worker may execute using `pm.max_requests=1`.

    A PHP execution timeout should be treated like another fatal error. Prevent attacker controlled requests from predictably reaching `Maximum execution time exceeded` while PHP is inside an affected operation. Changing the time limit only removes that possible interruption and does not mitigate the other cases.

    ### Logging and configuration audit

    Enable `log_errors=On`, a functional `error_log`, and `error_reporting=E_ALL` in startup configuration during an isolated audit. Review Apache, PHP-FPM, reverse proxy and service logs for:

    - Warnings, deprecations and core errors repeated before target scripts run.
    - Warnings and other diagnostics produced during extension or server cleanup.
    - Fatal, parse and uncaught error messages.
    - `Maximum execution time exceeded`.
    - Failures restricted to routes, content types, files, callback implementations or plugin options controlled by an attacker.

    Fixing observed errors reduces exposure, but absence of an error in logs is not proof of safety. Historical logs may have been collected with deprecations or other relevant severities excluded. Even an audit using `E_ALL` only covers the routes and application states that were exercised. A failure may also happen before PHP writes the message. Logs must supplement a static configuration and application flow audit.

    **Important**: Make sure to also follow the remediation advice from the related report.
    https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
    ```

## Conditions et limites — texte original PHP

    ```
    ### Producers

    A producing operation becomes dangerous when its request-owned state remains published after the request heap is freed. A fatal error can cause this by abandoning the operation before it resets the state. Fatal interruptions include parse and compile failures, uncaught errors, failure of `require`, and `Maximum execution time exceeded`.

    OOM can provide the same interruption when an affected error, exception, object or extension state was already published.

    Even a nonfatal diagnostic from extension or server cleanup during a later shutdown stage can repopulate new request-owned error information to the global state.

    ### Consumers

    There are two confirmed consumers before normal initialization.

    #### INI diagnostics before request initialization

    A warning, notice or deprecation during initialization can consume stale error state. It does not need to be fatal, displayed or logged. Such a warning may be raised when applying invalid or deprecated INI settings before ordinary executor initialization. Examples include:

    - Deterministic deprecations such as `auto_detect_line_endings=1`, a `filter.default` value other than the default, PHP 8.3+ legacy `assert.*` settings, PHP 8.4+ legacy session settings, and PHP 8.5 `report_memleaks=0` or nonzero `intl.error_level`.
    - Explicitly configured `mbstring.http_input`, `mbstring.http_output`, `mbstring.internal_encoding`, `iconv.input_encoding`, `iconv.output_encoding` or `iconv.internal_encoding`.
    - Invalid or conflicting `zend.assertions`, `memory_limit`, `date.timezone`, DBA, EXIF, mail, OpenSSL, zlib and loaded extension values.
    - Malformed or overflowing quantities, including invalid `memory_limit`, body size, input, timeout, stack and extension values on PHP 8.2+.
    - Configured log, mail, session or SOAP cache paths rejected under `open_basedir`.

    Global state is accessed before PHP decides whether to report, display or log the warning. Changing `error_reporting`, using `@`, or disabling `display_errors` or `log_errors` does not protect against this vulnerability.

    ##### Reachability

    With Apache mod_php, `.htaccess` and Apache `php_value`/`php_flag`/`php_admin_*` directory configuration is applied before `php_request_startup()`. Normal `php.ini` is startup configuration and is not reapplied as a consumer across requests.

    FPM is conditionally exposed when nginx, Apache `mod_proxy_fcgi` or another frontend sends `PHP_VALUE`/`PHP_ADMIN_VALUE` parameters that produce a diagnostic before request initialization. FPM pool values are applied when a worker starts, and `.user.ini` is applied after normal initialization. They do not provide the same early consumer. FPM also exits a child after `php_request_startup()` returns failure.

    LSAPI can apply special environment INI values early and is a conditional candidate. An equivalent early configuration consumer was not established in the default configuration of FrankenPHP. This does not make this environment immune. It may expose different consumers through application or extension behavior.

    #### Session upload progress before normal initialization

    Session upload progress can reach session handling before ordinary session initialization. It can therefore consume session or decoder state left by an interrupted request before normal initialization resets it. This consumer is independent of the INI diagnostic path and does not require a diagnostic from configuration.

    ## Concrete and candidate cases

    ### PHP 8.5 fatal error backtrace: confirmed

    With `fatal_error_backtraces` enabled, fatal error reporting stores backtrace state owned by the request. Resetting of this global state is always missed during shutdown. A diagnostic on a subsequent request reaches the stale value before normal request initialization resets it.

    This is the strongest demonstrated case and is the basis of the confirmed mod_php exploitation.

    ### Session upload progress lifecycle: confirmed

    An upload can initialize request-owned session and decoding state before normal module initialization. OOM or another fatal error after that state has been published can prevent its matching reset. PHP then frees the request heap while persistent session or decoder globals still refer to it. A later upload progress operation reaches those globals before ordinary initialization and treats them as valid state.

    The demonstrated application-independent trigger is OOM during input processing. Other fatal errors at this stage can cause the same state transition, but generally require additional application, extension or configuration conditions.

    With mod_php, both the producing operation and fatal error can occur during multipart startup. FPM terminates a child when this startup fails, so that exact sequence does not survive. The validated FPM path instead publishes state during application execution after successful startup, reaches a fatal error, and then uses session upload progress as the early consumer. It works with a normal dynamic FPM pool, although it depends on a suitable application operation.

    Session upload progress is enabled by default, and no application call to `session_start()` is required. It can supply a producer, consumer or both, but exploitation still requires an interruption after state is published and a subsequent request handled by the same worker.

    ### Other error, exception, object and extension state: conditional

    Supported PHP branches contain other request state that may become unsafe after a request boundary. The complete patch resets this wider state because it must not survive into operations that precede normal initialization. Whether it is reachable depends on the application, extensions and the exact point where the state was published.

    Fatal errors inside PHP operations that call back into an application deserve particular attention. The callback may introduce a fatal error while the operation still has temporary state. Applicability depends on a route reachable by an attacker, the callbacks registered by that application or extension, and a later consumer before normal request initialization. There is no configuration based mitigation that covers every such operation.
    ```

PoC : attestation publique officielle de démonstration sous conditions ; code d’exploit
public non vérifié. Exploitation en milieu naturel non établie par ces sources. 
Présence locale non établie.

CVSS 4.0 : 9.2 — CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
