CVE-2022-25139 is a critical security vulnerability disclosed in early 2022. It affects njs, a JavaScript-like scripting engine used in NGINX for scripting and extending web server behavior. Specifically, all versions up to and including njs .7. are vulnerable. The issue is a heap use-after-free in the function njs_await_fulfilled, potentially allowing attackers to execute arbitrary code, cause server crashes, or leak sensitive information.
This post explains CVE-2022-25139 in simple terms and provides:
If your NGINX configuration uses statements like this
js_include myscript.js;
js_set $dynamic_var some_js_function;
… it means you’re running scripts via njs, and you could be exposed if running a vulnerable version.
What is Use-After-Free?
Software uses *heap* memory to store data. When memory is *freed* but still accessed (used), it’s called use-after-free. If an attacker can control exactly what happens after the free, they may hijack program flow, cause a crash, or read/write arbitrary memory.
Where in njs Does This Happen?
In njs up to v.7., the function njs_await_fulfilled (involved in Promise resolution and async/await) mishandled memory. An object might be freed, but then used again after freeing–hence, use-after-free.
From the fix:
https://github.com/nginx/njs/commit/1ae7629e4d51b92712bb23d816fd33e8acc3c77
Patch summary:
The reference counting/buffering for promise resolution was incorrect, and a sequence of async events could access already-freed memory.
Code Snippet: Vulnerable Scenario
Let’s simulate a scenario relevant to production NGINX. Here is a sample myscript.js using async/await:
function handler(r) {
let promise = new Promise((resolve, reject) => {
// custom async logic
r.log("Promise created");
resolve("done");
});
promise.then((result) => {
r.log("Promise resolved: " + result);
});
return promise;
}
If attacker can trigger async logic in a certain way, a malicious script could attempt to manipulate the object during promise state transitions—potentially triggering the bug in njs_await_fulfilled.
The trick is to resolve a promise, but then do something that accesses its internals after the JS engine has already freed the object.
A hypothetical minimal PoC (proof-of-concept) in pure njs might look like
let p = Promise.resolve();
p.then(() => {
// The following exploits a gap in reference lifetime.
Object.defineProperty(p, 'then', {
get: function() {
// This unexpected access can trigger the bug internally.
// (Would be more effective with complex promise chains
// and custom async functions.)
}
});
});
*Note: Actual exploits would require deeper control and knowledge of njs internals.*
Exploit Potential
- Remote crash: Malicious users could make the NGINX worker process crash, causing a denial of service.
- Remote code execution: If attackers can control memory contents after free, they might hijack program control flow.
Data leakage: Attackers could potentially read freed memory, leaking sensitive information.
The risk is especially high for NGINX servers exposing API/script endpoints to untrusted users.
Mitigation & Patch
Upgrade njs to .7.1 or later.
Patch commit:
https://github.com/nginx/njs/commit/1ae7629e4d51b92712bb23d816fd33e8acc3c77
Check your NGINX install
njs --version
Or in NGINX logs, look for njs module version.
If you use njs in production, you must update.
Alternatively, disable js_* directives until patched.
References
- CVE-2022-25139 official: https://nvd.nist.gov/vuln/detail/CVE-2022-25139
- njs GitHub: https://github.com/nginx/njs
- Vulnerability patch: https://github.com/nginx/njs/commit/1ae7629e4d51b92712bb23d816fd33e8acc3c77
Conclusion
CVE-2022-25139 is a critical bug in njs up to .7., used widely in modern NGINX environments for scripting. The problem: mishandled memory in some async Promise scenarios. If you use JavaScript in your NGINX configs, upgrade immediately to avoid risk of crashes or worse.
Stay secure, keep your stack up-to-date, and always review changelogs for embedded scripting engines like njs.
*(This post is original content, crafted for clarity about CVE-2022-25139. If sharing, please link back to official references.)*
Timeline
Published on: 02/14/2022 22:15:00 UTC
Last modified on: 03/24/2022 14:35:00 UTC