Skip to main content

FrankenPHP EUVDEUVD-2026-98911

| CVE-2026-82416 HIGH
Race Condition (CWE-362)
2026-10-13 GitHub_M GHSA-v3ph-cgqh-r8p5
7.7
CVSS 3.1 · Vendor: GitHub_M
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Identify FrankenPHP worker mode with shared session module
  2. Delivery
    Flood concurrent requests to session endpoint
  3. Exploit
    Win PS(id) reset race across worker thread
  4. Execution
    session_id() returns another client's identifier
  5. Impact
    Hijack authenticated cross-user session

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A06:2025 - Insecure Design
ASVS 5.0
V15 - Secure Coding and Architecture Concurrency control, locking
MITRE ATT&CK

1 technique across 1 tactic: Privilege Escalation

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Requires FrankenPHP (prior to 1.12.5) running in worker mode where the PHP session extension is loaded as a shared/dynamic module and HAVE_PHP_SESSION is not defined at compile time, so frankenphp_reset_session_state() is compiled out and PS(id) persists across request boundaries; the target application must use PHP sessions and must receive concurrent requests on the same worker thread for the race to manifest. LIMITING FACTORS: builds that statically link the session extension - including the official static binaries and official Docker images - are NOT vulnerable; non-worker (classic) mode is not implicated; and the stale/cross-user identifier leak is intermittent and timing-dependent rather than deterministic. Fixed in 1.12.5, which resets the session module via the registry for shared-module builds.

Impact

Signals conflict in a way that lowers real-world priority well below the raw CVSS 7.7. The provided CVSS:3.1 vector (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L) correctly reflects network reach and no authentication, but the AC:H flag is doing heavy lifting: exploitation depends on both a race window across concurrent requests (CWE-362) AND a narrow, non-default build configuration where the PHP session extension is loaded as a shared module with HAVE_PHP_SESSION undefined at compile time. No EPSS score was provided, there is no CISA KEV listing, and no public exploit was identified - the only 'source code evidence' supplied is the vendor fix diff (PR #2523), not weaponized exploit code. The high C:H/I:H ratings (cross-user session exposure and session hijacking) are genuine and serious where the condition is met, but the official static binaries and official Docker images are explicitly NOT affected because they statically link the session extension. Net assessment: a legitimately high-impact bug that is a real priority only for the subset of operators running custom/distro builds with a dynamically-loaded session module in worker mode; for everyone on official distributions it is effectively not exploitable. Note the input Tags include 'Docker' even though the advisory states official Docker images are unaffected - treat the Docker tag as product-context, not an indicator of exposure.

Exploit ScenarioDerived

An attacker repeatedly issues concurrent requests to a session-backed endpoint of a FrankenPHP worker-mode server built with the session extension as a shared module. Because frankenphp_reset_session_state() is compiled out and PS(id) survives the request boundary, a crafted burst can race the session handler so session_id() returns another in-flight client's identifier, letting the attacker ride an authenticated victim's session. No public exploit code exists at time of analysis; the attack is timing-dependent (AC:H) and requires the vulnerable, non-default build configuration.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available 0.2% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Oct 13, 2026

Unauthenticated remote attackers can obtain another client's PHP session identifier from FrankenPHP worker mode before 1.12.5 when the session extension is loaded as a shared module rather than statically compiled in. Because frankenphp_reset_session_state() is compiled out under that build configuration, PS(id) persists across request boundaries on the same worker thread, so a later session_start() may keep a stale identifier instead of adopting the new request's cookie, and under concurrent requests session_id() can return a different user's identifier - enabling information disclosure, session hijacking, and intermittent logouts, with integrity and availability also impacted (CVSS 7.7, AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L, CWE-362). Exposure is conditional: official static binaries and Docker images that link the session extension statically are not affected, non-worker (classic) mode is not implicated, and the leak is intermittent and timing-dependent; no public exploit code or confirmed active exploitation was identified at time of analysis.

RemediationAI

Upgrade to FrankenPHP 1.12.5 (release tag caddy/v1.12.5) as the primary fix, per the vendor advisory at https://github.com/php/frankenphp/security/advisories/GHSA-v3ph-cgqh-r8p5; the upstream change in PR #2523 (commit be24d82531675f90862b8cde1e9fc7e9ee855aa5) adds "session" to MODULES_TO_RELOAD for builds without HAVE_PHP_SESSION so PS(id) is reset between worker requests. If immediate upgrade is not possible, switch to an official static binary or the official Docker image, which link the session extension statically and are not affected - the trade-off is adopting the vendor's fixed module set and container packaging. Alternative compensating controls: (a) rebuild FrankenPHP with the session extension statically compiled (configure --enable-session) and define HAVE_PHP_SESSION, accepting a rebuild and redeploy cycle; (b) where session state must be preserved separately, migrate session storage to a shared backend and use application-level session identifiers rather than relying on PHP's PS(id), which requires code changes; or (c) run in non-worker (classic) mode to eliminate the shared-interpreter state carry-over, at the cost of significantly higher per-request bootstrap overhead. Note that the upstream fix relies on the session module's RSHUTDOWN, which frees save handlers registered from the worker bootstrap - test custom session save handlers after applying the patch. As detection, correlate session identifiers observed across distinct clients in logs and treat unexplained cross-user CSRF token/session reuse as a possible sign of this race.

Affected VersionsENISA

frankenphp < 1.12.5

Affected Packages

go github.com/dunglas/frankenphp fix: 1.12.5
euvd frankenphp fix: 1.12.5

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 2 packages in go, euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

FrankenPHP is a Caddy-based application server that runs PHP in a worker mode, keeping a PHP interpreter alive across many requests to avoid per-request bootstrap cost. That design requires explicitly clearing per-request interpreter state between requests. The affected code path is guarded by the compile-time macro HAVE_PHP_SESSION: when the PHP session extension is not visible at build time - the typical case when it is loaded dynamically as a shared module (extension=session.so) rather than linked in - frankenphp_reset_session_state() is not compiled, so the session globals (PS(id) and related state held in the PHP session module) survive the request boundary. A subsequent session_start() then sees an identifier already present and can skip adopting the incoming request's session cookie, causing session_id() to return a stale identifier from a prior request or, when requests interleave concurrently on the same worker thread, another client's identifier. This is a classic CWE-362 concurrent execution using shared resource with improper synchronization: a per-thread interpreter is reused while session state is not reset, so state from one request leaks into another. The upstream fix in PR #2523 broadens the MODULES_TO_RELOAD list to include "session" when HAVE_PHP_SESSION is undefined, forcing the session module through the module RSHUTDOWN path so PS(id) is cleared between worker requests; the commit explicitly notes that this RSHUTDOWN frees save handlers registered during worker bootstrap, an accepted trade-off for builds where the extension is not statically linked. CPE data (cpe:2.3:a:php:frankenphp:*:*:*:*:*:*:*:*) marks the entire pre-fix product line, but per the advisory the practical exposure is limited to shared-module session builds.

Know when Frankenphp gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (GitHub_M) PRIMARY 7.7 HIGH
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L
vuln.today AI 7.7 HIGH

Network-reachable with no auth (PR:N), but a race window plus a non-default shared-module build is required (AC:H); cross-user session exposure gives C:H/I:H and intermittent logout gives A:L.

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L
4.0 AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N

Primary rating from Vendor (GitHub_M).

CVSS VectorVendor: GitHub_M

Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
Low

Lifecycle Timeline

2
Patch available
Oct 13, 2026 - 18:19 EUVD
CVE Published
Oct 13, 2026 - 16:20 cve.org
HIGH 7.7

DescriptionCVE.org

FrankenPHP is a modern application server for PHP. Prior to 1.12.5, FrankenPHP worker mode can retain PHP session state between requests when the session extension is loaded as a shared module and is unavailable through HAVE_PHP_SESSION at compile time. In this build configuration, frankenphp_reset_session_state() is compiled out, PS(id) can survive a request boundary, and a subsequent session_start() can ignore the new request's cookie because an identifier is already present. Under concurrent requests, session_id() can therefore return another client's identifier or a stale identifier from a previous request on the same worker thread, causing cross-user session exposure, possible session hijacking, and intermittent logout behavior. Builds with the session extension statically linked, including the official static binaries and Docker images, are not affected. This issue is fixed in version 1.12.5.

Technical POC Analysis

CWE-362 (race condition / concurrent access to a shared resource), with the advisory also classifying the impact as CWE-488 (exposure of a data element to the wrong session).

Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.

Executive ViewAI

Why It Matters

FrankenPHP worker mode deployments prior to version 1.12.5 that load the PHP session extension as a shared module are vulnerable to unauthenticated session identifier leakage, enabling session hijacking, information disclosure, and intermittent logouts. This affects organizations relying on this configuration for concurrent request handling, potentially exposing user accounts and sensitive data while disrupting service availability. Leadership should prioritize remediation because the flaw can be exploited remotely without credentials, though exposure is conditional on the specific build configuration and no public exploit identified at time of analysis.

Business Impact: High
Compensating Controls

Use official static binaries or Docker images that link the session extension statically; avoid worker mode with a shared session module; switch to classic (non-worker) mode; implement strict session monitoring and anomaly detection; limit network exposure of affected services.

Threat Intelligence Overview

EPSS Score
0.2%
Top 87% exploitable
Prevalence
Low
modern niche PHP app server; official static/Docker builds unaffected
Threat Intel
1
1 source
Data Quality
6 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment GHSA GitHub

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC No
EPSS 0.2%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Scheduled
Exploitation
None
System Exposure· derived
Open
Automatable
No
Human Impact
High
Technical Impact
Total

Priority Score

38
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +38
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.

Race conditions occur when multiple concurrent requests exploit the brief time gap between checking a condition and acting upon it (TOCTOU - Time of Check, Time of Use).

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy