
Cloud Vulnerability DB
A community-led vulnerabilities database
CVE-2026-33993 is a prototype pollution vulnerability in the unserialize() function of the locutus npm package (a JavaScript port of PHP functions), classified as CWE-1321. The flaw allows an unauthenticated, network-accessible attacker to inject attacker-controlled properties into deserialized objects by supplying a PHP-serialized payload containing __proto__ as a key. All versions of locutus prior to 3.0.25 for Node.js are affected. The advisory was published on March 25, 2026, and the CVE was assigned on March 27, 2026. The CVSS v3.1 base score is 9.8 (Critical), while the CVSS v4.0 base score is 6.9 (Medium) (Github Advisory, Locutus Advisory).
The root cause (CWE-1321) lies in two functions within src/php/var/unserialize.ts: expectArrayItems() (line 358) and expectObject() (line 278). Both create plain JavaScript objects ({}) and assign user-controlled keys via bracket notation — items[String(key[0])] = item[0] — without filtering the __proto__ key. When __proto__ is used as a key, JavaScript's __proto__ setter is invoked, replacing the deserialized object's prototype with attacker-controlled content rather than creating a regular property. This is distinct from previously reported prototype pollution in parse_str (GHSA-f98m-q3hr-p5wq), which had a regex guard that was never applied to unserialize. Notably, this is not global Object.prototype pollution — only the specific deserialized object's prototype is replaced, limiting blast radius but still enabling meaningful attacks. Proof-of-concept code is publicly available in the security advisory (Locutus Advisory, Fix Commit).
Successful exploitation enables three distinct attack scenarios: (1) Authorization bypass — injected prototype properties become accessible via dot notation and the in operator while remaining invisible to Object.keys(), JSON.stringify(), and hasOwnProperty(), allowing bypass of checks like if (config.isAdmin) or if ('role' in config); (2) Privilege escalation via property propagation — when consuming code copies the deserialized object using for...in loops (a common JavaScript cloning pattern), injected prototype properties materialize as real own properties that survive all subsequent hasOwnProperty checks; (3) Denial of service — the attacker can override hasOwnProperty, toString, valueOf, and other Object.prototype methods with non-function values, causing TypeError exceptions when those methods are called. The primary attack surface is applications that deserialize PHP-serialized data from external or untrusted sources, which is the primary use case for locutus unserialize (Locutus Advisory).
A proof-of-concept exploit is publicly available in the GitHub security advisory, consisting of multiple runnable JavaScript code snippets that demonstrate all three attack scenarios (property injection, for...in propagation, and method override DoS) by directly calling unserialize() with crafted payloads (Locutus Advisory). No authentication or user interaction is required, and attack complexity is low. There is no evidence of in-the-wild exploitation at this time, and the vulnerability is not listed in the CISA KEV catalog. The EPSS score is approximately 0.055% (18th percentile), indicating a low current probability of exploitation in the next 30 days (Github Advisory). No threat actor attribution has been reported.
locutus versions prior to 3.0.25 and passes externally supplied PHP-serialized data to the unserialize() function (e.g., data received from a web request, database, or inter-service communication).__proto__ as an array or object key with attacker-controlled properties. For authorization bypass: a:2:{s:9:"__proto__";a:1:{s:7:"isAdmin";b:1;}s:4:"name";s:3:"bob";}. For DoS: a:1:{s:9:"__proto__";a:1:{s:14:"hasOwnProperty";b:1;}}.unserialize() — such as an HTTP request body, query parameter, cookie, or API field.expectArrayItems() or expectObject() function assigns the __proto__ key via bracket notation, invoking JavaScript's __proto__ setter and replacing the deserialized object's prototype with the attacker-supplied content.if (config.isAdmin) or if ('role' in config) and grants elevated access because the injected property is accessible via prototype chain; (b) For propagation — if the application copies the object with for...in, injected properties become real own properties; (c) For DoS — call any overridden method (e.g., obj.hasOwnProperty('x')) to trigger a TypeError and crash the handler (Locutus Advisory).__proto__ as a key (e.g., payloads matching the pattern s:9:"__proto__" in request bodies, cookies, or API parameters.TypeError: obj.hasOwnProperty is not a function or similar TypeError exceptions originating from deserialization code paths, which may indicate a DoS attempt.'isAdmin' in obj returns true but obj.hasOwnProperty('isAdmin') returns false, or where Object.keys(obj) does not include properties that are accessible via dot notation (Locutus Advisory).The primary remediation is to upgrade locutus to version 3.0.25 or later, which hardens src/php/var/unserialize.ts by routing __proto__, constructor, and prototype keys through Object.defineProperty() instead of bracket notation assignment, preventing prototype setter invocation (Locutus Release, Fix PR). If immediate patching is not possible, apply the following interim mitigations: (1) validate and sanitize all PHP-serialized input before passing it to unserialize(), rejecting payloads containing __proto__, constructor, or prototype as keys; (2) avoid using for...in loops to copy or spread deserialized objects; (3) implement a property allowlist on deserialized configuration objects; (4) use Object.create(null) for objects that will hold deserialized data, as null-prototype objects are immune to __proto__ setter invocation (Locutus Advisory).
The locutus maintainer (kvz) confirmed the vulnerability, reproduced it locally against locutus@3.0.24, and shipped the fix in version 3.0.25 on the same day the advisory was published (March 25, 2026), demonstrating a rapid response (Locutus Advisory). The advisory notes this is distinct from previously reported prototype pollution in parse_str (GHSA-f98m-q3hr-p5wq, GHSA-rxrv-835q-v5mh), highlighting a pattern of prototype pollution issues in the package's PHP deserialization functions. A Bluesky post referencing the CVE was observed shortly after disclosure, and the vulnerability was indexed by multiple threat intelligence aggregators including VulDB, CIRCL, and CVEFeed within hours of publication.
Fix availability across major Linux distributions and their releases.
Source: This report was generated using AI
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."