CVE-2026-73649
Summary
Remote Code Execution (RCE) in velocityjs v2.1.6 via property-read to the Function constructor. This bypasses the fix for GHSA-j658-c2gf-x6pq ("Prototype Pollution in #set path assignment") — that advisory blocked constructor/proto/prototype only in the #set assignment handler (set.cjs), but property read expressions are unfiltered. Any application rendering attacker-controlled Velocity templates is vulnerable to arbitrary code execution on the server.
Details
GHSA-j658-c2gf-x6pq added isBlockedPathKey() to dist/cjs/compile/set.cjs:35-43, which blocks proto, constructor, and prototype keys. However, this check only runs when the #set directive assigns a value — it validates the assignment target path, not the value expression being evaluated.
The value expression is evaluated via getReferences() in dist/cjs/compile/references.cjs:16, which calls getAttributes() at line 81. The property access at line 88-89 has no filtering:
// references.cjs:81-91
getAttributes(property, baseRef, ast) {
if (property.type === "property") {
return baseRef[property.id]; // ← NO BLOCK on "constructor", "prototype", etc.
}
...
}
Meanwhile, set.cjs:35-43 properly blocks these keys, but only for the #set target:
// set.cjs:35-43
isBlockedPathKey(baseRef, key, isEnd) {
if (key === PROTO_KEY) return true; // "proto"
if (key === "prototype" && typeof baseRef === "function") return true;
return !isEnd && PROTOTYPE_CHAIN_KEYS.has(key) && !hasOwnProperty(baseRef, key);
}
The exploit chain:
1. $x.constructor → getAttributes() → {}["constructor"] → Object
2. .constructor → getAttributes() → Object["constructor"] → Function
3. ("return process.mainModule.require('child_process').execSync('whoami')") → calls Function(...) → creates a function
4. The #set assigns the result to $f, which is then rendered as $r
The #set handler validates $f as the assignment target (which passes — f is not blocked), but never inspects the right-hand expression for prototype chain traversal.
PoC
const veloc
⚡ Watch CVE-2026-73649
Get an email if CVE-2026-73649 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.
Exploitation outlook
- Low exploitation risk0.50% 30-day exploitation probability — currently an unlikely target, but scores change as exploit code circulates. Riskier than 41% of all EPSS-scored CVEs.
Advisory coverage (2)
External references
Embed the live status
— this badge updates automatically when the KEV or exploit status changes. How to embed it →
[](https://www.csirts.com/cve/CVE-2026-73649)