PHP SOAP: CVE-2026-6722 — unauthenticated use-after-free RCE in ext-soap (plus four more PHP findings in the same release)
Picked up on request — not a daily item; the disclosure is from 12 May 2026. The PHP security team closed a cluster of findings in the SOAP extension via advisory GHSA-85c2-q967-79q5, led by CVE-2026-6722: a use-after-free in ext-soap that can be developed into unauthenticated remote code execution (CVSS 4.0 base 9.5 per databases/reporting). The cause is object deduplication via id/href, which stores PHP objects in a global map without incrementing the refcount. If you run no SoapServer against untrusted input you're fine on the RCE path — but the same release also closes a urldecode() finding that affects every PHP stack: so pull 8.2.31 / 8.3.31 / 8.4.21 / 8.5.6 anyway.
TL;DR — 90 seconds
Affected?
PHP applications running a SoapServer that parse untrusted SOAP requests (RCE path, CVE-2026-6722); additionally every PHP stack via the urldecode() OOB read (CVE-2026-7258) — independent of SOAP. Affected branches: PHP before 8.2.31, 8.3.31, 8.4.21, 8.5.6 (the mbstring finding only before 8.4.21 / 8.5.6).
Risk?
CVE-2026-6722: use-after-free → unauthenticated RCE (CVSS 4.0 base 9.5 per DB/reporting). Others: CVE-2026-7261 UAF (SoapServer/session), CVE-2026-7262 NULL deref → DoS, CVE-2026-7258 OOB read in urldecode(), CVE-2026-6104 mbstring overrun (info disclosure).
Immediate action?
Pull the relevant patch release (8.2.31 / 8.3.31 / 8.4.21 / 8.5.6). Where SOAP is not needed: do not load ext-soap at all. Do not run a SoapServer against untrusted input without the patch.
Recommendation?
Mid-market and enterprise: treat the PHP point release as a regular but prioritised bump; inventory ext-soap presence in the stack (including transitively via legacy integrations/libs); put SoapServer endpoints behind auth/allowlist.
Criticality?
high (references the hero badge — unauth RCE path on SoapServer exposure; the urldecode() part affects all PHP stacks).
What is the problem?
The PHP SOAP extension has a long history of memory-corruption bugs — but this round crosses the line into unauthenticated RCE. The central finding, CVE-2026-6722, sits in how ext-soap, when parsing an XML document, deduplicates objects in the XML graph via the id and href attributes: the extension stores plain PHP objects in a global hash map but fails to increment the reference count. Via the “Apache map” mechanism an attacker can deliberately free these objects by overwriting existing map entries — the freed memory segment then becomes reusable. Per researcher Brett Gervasoni, this memory can subsequently be highly controlled by allocating plain strings, escalating the flaw to full remote code execution.
Decisive for severity: exploitation merely requires sending a crafted SOAP request body to a PHP endpoint that invokes the SOAP extension to parse client input — without authentication, if the endpoint accepts unauthenticated SOAP traffic. That is exactly the classic SOAP-server constellation. Reporting/DBs list CVE-2026-6722 at CVSS 4.0 base 9.5 as critical (the initial pickup also calls it “high-severity” — I report both honestly and derive the severity primarily from “remote + unauth + RCE”, not from a single number).
Alongside the RCE finding the PHP team addressed four more, moderate vulnerabilities via GitHub in the same batch. CVE-2026-7261 is another use-after-free in the SoapServer when handling session-persisted objects: if a header node's handler function fails or throws, the object is incorrectly freed but still written to session storage. CVE-2026-7262 is a NULL pointer dereference when decoding “Apache: Map” nodes — an XML request without a value node reliably crashes the PHP process (DoS). CVE-2026-7258 is an out-of-bounds read in the native urldecode() function (missing type cast when evaluating hex characters, negative byte values → segfault on some platforms, e.g. NetBSD) — this finding affects PHP independent of SOAP. And CVE-2026-6104 affects the mbstring extension: encoding names with embedded NUL bytes trigger a global buffer overrun (information disclosure, not directly RCE-capable).
Who is affected?
Affected
Not affected
Conditions / aggravating
PHP apps with a SoapServer that parse untrusted SOAP requests
Apps without ext-soap or without a SoapServer on untrusted input
CVE-2026-6722/-7261/-7262: the trigger is a crafted SOAP/XML request to a parsing endpoint; for 6722without auth if the endpoint accepts unauth SOAP
Every PHP stack via urldecode()
— (the finding is SOAP-independent)
CVE-2026-7258: OOB read in urldecode(); platform-dependent segfault (e.g. NetBSD) — affects branches before 8.2.31/8.3.31/8.4.21/8.5.6
Stacks with mbstring and untrusted encoding names
Stacks that do not process external encoding names
CVE-2026-6104: only PHP before 8.4.21 / 8.5.6; info disclosure, not directly RCE
PHP before 8.2.31, 8.3.31, 8.4.21, 8.5.6 (SOAP + urldecode findings across all four branches)
PHP on the patched releases
mbstring finding tightly limited to 8.4/8.5; SOAP/urldecode across all four active branches
Important for my context and to be honest: the spectacular part — the unauth RCE — only bites if a SoapServer actually processes untrusted input. If you no longer run SOAP, you are not exposed here. The unremarkable part — urldecode() — is the real breadth, because urldecode() appears in countless stacks and the finding is SOAP-independent. The patch list (8.2.31 / 8.3.31 / 8.4.21 / 8.5.6) is the authoritative reference; always reconcile concrete version levels against the PHP advisory or your own distribution.
Impact
The operational severity splits into two very different profiles. CVE-2026-6722 is the worst-case profile: a single crafted SOAP body against an unauthenticated SoapServer can — via the controlled re-occupation of the freed memory with strings — lead to remote code execution. That is full takeover of the worker, with no precondition other than “the endpoint parses my SOAP input”. Exactly this constellation (a publicly reachable SOAP endpoint without auth) is common in legacy integrations, B2B interfaces and legacy web services — and often forgotten.
The other four findings are less dramatic but not irrelevant. CVE-2026-7261 (UAF in the SoapServer/session) and CVE-2026-7262 (NULL deref → DoS) broaden the SOAP attack surface with crashes and potential follow-on corruption. CVE-2026-7258 is the one that affects everyone: urldecode() is called en masse in routing, query parsing, form handling and third-party libraries; an OOB read with a platform-dependent segfault is primarily a stability/DoS issue but for exactly that reason belongs in every patch plan. CVE-2026-6104 (mbstring) is an info disclosure via a global buffer overrun when parsing encoding names with NUL bytes — not directly usable for code execution, but a leak.
There is no single, uniform CVSS number for the whole cluster; the source gives CVSS 4.0 base 9.5 (critical) for 6722 and rates the others as moderate. Operationally I treat the cluster as “a PHP point release that needs to go in anyway — with an RCE finding on top if SOAP is exposed”.
Mitigation / immediate steps
Note: the following steps are my operational recommendation based on the documented findings and fix versions — not a vendor-certified guide. Reconcile concrete version levels against the PHP advisory GHSA-85c2-q967-79q5 or your distribution.
Operational Decision Block
Act now if … a SoapServer parses untrusted/unauthenticated SOAP input (RCE path CVE-2026-6722).
Check with priority if … your PHP stack runs on a branch before 8.2.31/8.3.31/8.4.21/8.5.6 — because of the SOAP-independent urldecode() finding that is practically everyone.
Awareness only if … you are already on the patch release and do not load ext-soap.
Step 1 — Pull PHP to the patch release
# check current version
php -v
# target releases: 8.2.31 / 8.3.31 / 8.4.21 / 8.5.6 (branch-appropriate)
# Debian/Ubuntu (distribution usually ships backported fixes):
apt-get update && apt-get install --only-upgrade php php-cli php-fpm php-soap php-mbstring
# container: raise the base image to patched PHP and rebuild
Step 2 — Eliminate the SOAP attack surface where not needed
# is ext-soap loaded at all? (often loaded unnoticed)
php -m | grep -i soap
# if SOAP is not needed: do not load the extension
# - php.ini / conf.d: comment out/remove the soap extension
# - in the container: don't build the module in at all (drop docker-php-ext-install soap)
- put SoapServer endpoints behind authentication/allowlist
(CVE-2026-6722 is unauth ONLY if the endpoint accepts unauth SOAP)
- restrict publicly reachable SOAP endpoints at the reverse proxy
- WSDL/endpoint inventory: which services parse client SOAP? (often legacy/B2B)
Step 4 — Composer/stack inventory against ext-soap
# packages/integrations that require ext-soap (including transitively)
composer why-not ext-soap 2>/dev/null
grep -RIn "new SoapServer\|new SoapClient\|SoapServer(" --include=*.php .
Detection / verification
Check points derived from the documented findings and common PHP inventory practice.
Version & module inventory
# PHP version per host/container/FPM pool
php -v; php-fpm -v 2>/dev/null
# is soap/mbstring loaded?
php -m | grep -iE "soap|mbstring"
# scan container images, not just hosts
grype <image-ref> 2>/dev/null | grep -iE "php|ext-soap"
- PHP-FPM worker crashes/segfaults on SOAP requests (UAF/NULL-deref triggers)
- segfaults around urldecode() in logs (CVE-2026-7258), platform-dependent
- unusual child processes of a PHP-FPM worker (possible post-RCE on 6722)
- clustered 500s/worker restarts on SOAP endpoints (possible DoS, 7262)
Operator guidance
Mid-market
Apply the PHP point release — not because of SOAP but because of urldecode(): this finding affects your stack even if you never wrote a line of SOAP. While you're at it, check with php -m | grep -i soap whether ext-soap is loaded at all (often it is, from historical image defaults, without anyone using it) — if not, it should go, which permanently shrinks the attack surface. If a SoapServer does accept client input publicly somewhere, that's your urgent case: patch, or until then put it behind auth/allowlist.
Enterprise
Additionally: SBOM-/inventory-driven search for ext-soap across all images, FPM pools and legacy integrations — B2B/legacy web services in particular keep SOAP alive longer than project memory. Treat the PHP release as a prioritised security bump with its own SLA, not routine. For the urldecode() breadth, a quick look at platform-specific segfault telemetry pays off. Where a SoapServer must stay in production: enforce auth, limit input sizes, isolate the worker so a successful UAF does not turn into lateral movement.
Kubernetes / containers
Raise base images to patched PHP and rebuild; check whether soap/mbstring are even built in via docker-php-ext-install — if not needed, drop them. PHP-FPM pods that parse SOAP belong in a minimally privileged namespace with hard resource limits (against the DoS findings) and without broad outbound network access (limits the RCE blast radius). Restrict endpoint exposure via NetworkPolicy/Ingress.
Declarative stacks (NixOS / Talos / Flatcar)
The lever is the explicit feature matrix: anyone who builds PHP declaratively with exactly the needed extensions has ext-soap either deliberately in or cleanly out — no “it just came with the base image”. The rebuild onto the patched version is reproducible and provable, and a build without the SOAP extension at all is structurally unreachable for CVE-2026-6722/-7261/-7262. That is the clean default here for everyone who — like me — practically no longer uses SOAP.
What I actually did
Full disclosure: I practically no longer use SOAP in my managed stacks — so the RCE finding (CVE-2026-6722) is primarily an inventory and hygiene prompt for me, not a fire. On this occasion that meant: ran php -m | grep -i soap across the managed stacks to find loaded-but-unused ext-soap instances from old image defaults and remove them; a Composer/code sweep for SoapServer/SoapClient; and — the genuinely broad part — scheduled the PHP point releases (8.2.31 / 8.3.31 / 8.4.21 / 8.5.6) as a prioritised bump, because the urldecode() finding (CVE-2026-7258) affects every stack independent of SOAP.
The lesson is unspectacular but precisely for that reason valuable: a “disabled” technology is not the same as a “not loaded” technology. ext-soap rides along in many PHP images as a default even when the application has long moved to REST/JSON — and a loaded extension is attack surface whether used or not. So my standing recommendation here is not “patch SOAP” but “don't even load SOAP nobody needs anymore” — and pull the PHP release that's due anyway because of the non-SOAP findings.
A closer look: why deduplication becomes RCE
The core of CVE-2026-6722 is a classic refcount omission in an optimisation. SOAP XML can reference objects via id/href instead of duplicating them — the extension remembers object pointers in a global map for that. Correct would be to increment the reference count on storing, so the object is not freed while the map references it. That is exactly what does not happen: the pointer sits in the map, the refcount stays unchanged. Via the “Apache map” mechanism an attacker can overwrite the same map entry and thus free the original object while the (now orphaned) reference lives on — a textbook use-after-free. The step to RCE is then heap grooming: the freed segment can be re-occupied with plain PHP strings whose content the attacker controls; this turns “freed but referenced memory” into a controlled memory region. Lesson for your own code and extensions: any caching/dedup layer that holds raw pointers without ownership accounting is a UAF candidate — the optimisation must manage the lifecycle, not just the identity.
Frequently asked questions about the PHP SOAP findings
Am I affected by CVE-2026-6722 if I don't use SOAP at all?+
Not by the RCE path — it only bites if a SoapServer parses untrusted input. But beware: check with php -m | grep -i soap whether ext-soap is loaded anyway (often from old image defaults). And independent of SOAP, CVE-2026-7258 (OOB read in urldecode()) affects you regardless — it comes in the same patch release. So: pull PHP to 8.2.31/8.3.31/8.4.21/8.5.6 and unload unused ext-soap.
Which PHP versions close the SOAP RCE and the other findings?+
PHP 8.2.31, 8.3.31, 8.4.21 and 8.5.6 (patches by iluuu1994, iliaal, ndossche among others, advisory GHSA-85c2-q967-79q5). The SOAP and urldecode() findings affect all four active branches; the mbstring finding (CVE-2026-6104) only versions before 8.4.21/8.5.6. Reconcile concrete levels against the PHP advisory or your distribution, don't fix them from this post.
Is CVE-2026-6722 really exploitable without authentication?+
Yes — provided the endpoint accepts unauthenticated SOAP traffic. Per the source, exploitation only needs a crafted SOAP request body sent to a PHP endpoint that invokes the SOAP extension to parse client input. That is why publicly reachable SoapServer endpoints belong behind auth/allowlist until patched. The severity is given as CVSS 4.0 base 9.5 (critical); we derive it primarily from “remote + unauth + RCE”.
What is the “Apache map” mechanism the use-after-free runs through?+
SOAP XML can reference objects via id/href; the extension remembers object pointers in a global hash map for that — but without incrementing the refcount. Via the “Apache map” mechanism an attacker can overwrite the same map entry and thus free the object while the orphaned reference lives on (use-after-free). Subsequently allocating plain strings re-occupies the memory in a controlled way — the path to RCE.
Is it enough to disable ext-soap instead of patching PHP?+
Against the SOAP findings (6722/7261/7262) yes — a non-loaded extension is not attackable, and for stacks with no SOAP need, unloading is the clean permanent fix. But it does not close CVE-2026-7258 (urldecode()) and CVE-2026-6104 (mbstring). Best practice: unload unused ext-soapand apply the PHP point release.
Which of the five findings affects every PHP stack, even without SOAP?+
CVE-2026-7258 — an out-of-bounds read in the native urldecode() function (missing type cast for hex characters, negative byte values → segfault on some platforms like NetBSD). urldecode() is used en masse in routing, query/form parsing and many libraries, making this finding the real breadth of the release — regardless of whether you use SOAP.
Conclusion
For stacks still running SOAP in production, CVE-2026-6722 is a serious case: unauthenticated RCE via a single crafted request, with no precondition other than a parsing endpoint. For everyone else — me included — the picture is two-sided and unspectacular: the RCE path does not bite without a SoapServer, but the bundled urldecode() finding affects every PHP stack, so the point release needs to go in anyway. The standing lesson is the most valuable: “disabled” is not “not loaded” — an ext-soap that rides along as an image default is attack surface even when the app has long moved to REST. Unload unused SOAP, pull the due PHP release because of the non-SOAP findings, and put exposed SoapServers behind auth. Concrete version levels belong to the PHP advisory, not a snapshot. Not a 48h daily case — but a clean PHP hygiene prompt that sits too long if nobody picks it up explicitly.
Before a forgotten ext-soap takes over your worker — let's talk about your PHP hygiene.
I inventory, slim down and patch your PHP stack — including the ext-soap that rides along as an image default even though nobody uses it anymore.
ext-soap inventory across hosts, container images and FPM pools, removal of unused extensions, securing of exposed SoapServer endpoints (auth/allowlist), a prioritised PHP point-release bump (8.2.31 / 8.3.31 / 8.4.21 / 8.5.6) because of the SOAP and the SOAP-independent urldecode() findings, plus a reproducible rebuild with an explicit extension matrix.
Platform operations instead of advice-on-paper: I check, mitigate and validate production PHP stacks — from the extension inventory through endpoint hardening to the point release.
Programming since 2002 – self-taught, set up my own business with KO-Web in 2012. Over 100 projects, with a focus on security, performance, automation and quality. Today freelance: DevSecOps consulting, training and software development.