CVE-2026-33993: 
JavaScript vulnerability analysis and mitigation

Overview

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).

Technical details

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).

Impact

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).

Exploitability

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.

Exploitation steps

  1. Identify target: Locate a Node.js application that uses 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).
  2. Craft malicious payload: Construct a PHP-serialized string containing __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;}}.
  3. Submit payload: Deliver the crafted PHP-serialized string to the application through any input channel that feeds into unserialize() — such as an HTTP request body, query parameter, cookie, or API field.
  4. Trigger prototype injection: The vulnerable 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.
  5. Exploit the result: (a) For authorization bypass — the application evaluates 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).

Indicators of compromise

  • Network: Incoming requests containing PHP-serialized strings with __proto__ as a key (e.g., payloads matching the pattern s:9:"__proto__" in request bodies, cookies, or API parameters.
  • Logs: Application error logs showing TypeError: obj.hasOwnProperty is not a function or similar TypeError exceptions originating from deserialization code paths, which may indicate a DoS attempt.
  • Application Behavior: Unexpected privilege escalation events where users gain admin or elevated access without corresponding authentication events; authorization checks passing for users who should not have elevated roles.
  • Code/Runtime: Deserialized objects where '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).

Mitigation and workarounds

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).

Community reactions

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.

Additional resources

Linux Distribution fix status

Fix availability across major Linux distributions and their releases.

RHEL / CentOS

Affected

OpenShift

openshift-logging/elasticsearch-operator-bundle

Affected

Source: This report was generated using AI

Related JavaScript vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-966w-4vpf-p7hcHIGH7.1
  • JavaScript logoJavaScript
  • @aloma.io/aloma
NoYesOct 25, 2026
GHSA-mrwp-f3q8-3g9pMEDIUM5.9
  • JavaScript logoJavaScript
  • follow-redirects
NoYesOct 25, 2026
GHSA-hfm3-x63j-7fxpHIGHN/A
  • JavaScript logoJavaScript
  • @payload-auth-link/migrate
NoYesOct 25, 2026
GHSA-6244-vvv9-76f5MEDIUMN/A
  • JavaScript logoJavaScript
  • @payload-auth-link/plugin
NoYesOct 25, 2026
GHSA-q53q-qg98-p9jfHIGHN/A
  • JavaScript logoJavaScript
  • llm-fw
NoYesOct 25, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Additional Wiz resources

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management