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