The JavaScript ecosystem moves fast, but sometimes old code can hide big risks. One of those risks made headlines in early 2022 with the disclosure of CVE-2022-24999, a vulnerability affecting the hugely popular qs package before version 6.10.3, as used most famously in Express.js web servers (before Express 4.17.3).
If you’re running Express – or any web app using qs for parsing – keep reading: CVE-2022-24999 represents a simple attack that could hang your server, all from a single malicious URL.
What is qs and Why Should I Care?
qs is a widely used JavaScript library that parses URL query strings into JavaScript objects. For example, it turns the query string a=1&b=2 into {a: "1", b: "2"}.
Express.js (the go-to web server for Node.js apps) depends on qs internally to read query strings. Many other npm packages use it as well.
The Vulnerability: Prototype Pollution for Server Hangs
Before version 6.10.3, qs improperly handled "special" keys in query strings like __proto__. This allowed attackers to inject payloads that pollute the Object.prototype of your application.
The most common & impactful effect? If an attacker sends a specially crafted query string, they can cause your entire Node.js process (and thus your web app) to hang—all with one HTTP request.
Why __proto__ Is Dangerous
In JavaScript, every object is linked to a prototype. If an attacker can modify the Object.prototype via your query parser, they can break code assumptions, cause crashes, or, as in this case, create infinite loops or resource exhaustion.
Suppose you have a simple Express app
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json(req.query);
});
app.listen(300, () => console.log('Listening on port 300'));
If someone visits this URL
http://yourserver/?a[__proto__]=b&a[__proto__]&a[length]=100000000
The qs parser is tricked into setting dangerous properties on Object.prototype. This, in turn, can break standard array operations or even enter infinite work, such as:
const arr = [];
arr.length = req.query.a.length; // attacker has set this to 100000000, causing a hang!
You can easily simulate the hang—run the Express code above and visit
http://localhost:300/?a[__proto__]=b&a[__proto__]&a[length]=100000000
Your Node.js process will freeze or consume a lot of RAM/CPU.
a[__proto__]=b – Forces a’s prototype to contain a property, which then leaks to all objects
- a[length]=100000000 – Sets an enormous length property via the polluted proto, causing objects like Arrays to behave abnormally (e.g., a loop like for (let i = ; i < arr.length; i++) spins millions or billions of times!)
- By crafting these query string keys and values, an attacker can reliably hang or crash nearly any web server using vulnerable versions of Express/qs.
How to Fix the Vulnerability
The vulnerability is patched in qs versions:
Also backported to: 6.9.7, 6.8.3, 6.7.3, 6.6.1, 6.5.3, 6.4.1, 6.3.3, and 6.2.4
Express 4.17.3 ("deps: qs@6.9.7") is patched and safe.
How to upgrade
npm install express@4.17.3
or, if you use qs directly
npm install qs@6.10.3
Check your package-lock or yarn.lock to verify your actual versions!
Practical Defenses
1. Always keep dependencies up-to-date. Use npm audit or Snyk to monitor for vulnerable packages.
Sanitize your inputs. Don’t trust query strings, even from seemingly innocent places.
3. Use container/resource limits on your Node.js processes so that if something does go wrong, the damage is isolated.
References & Further Reading
- Official CVE: CVE-2022-24999
- GitHub Security Advisory for qs
- Snyk vulnerability report
- Express 4.17.3 Release Notes
Final Thoughts
This bug is a textbook case for why dependency hygiene matters. The qs bug sat undetected for years, putting Express-based apps at risk—even as the web depended more and more on these libraries.
Patch now! And, if you see strange hangs or server timeouts, check your query string parser. CVE-2022-24999 is a reminder that sometimes, a single line in a query string is all it takes for a server meltdown.
*Stay safe, and keep those dependencies current!*
*Written for devs & maintainers who want actionable security, not just the headlines. Please share and help secure the Node ecosystem!*
Timeline
Published on: 11/26/2022 22:15:00 UTC
Last modified on: 02/16/2023 19:19:00 UTC