nyx/docs/rules/javascript.md
Eli Peter 1bbe4b1cfb
Phase 1 (#33)
* chore: Exclude CLAUDE.md from Cargo.toml

* feat: add callgraph module and integrate into main analysis flow

* feat: enhance CLI with new severity filtering and analysis modes

* feat: update CHANGELOG with recent enhancements and fixes to severity filtering and output handling

* feat: implement state-model dataflow analysis for resource lifecycle and auth state

* feat: enhance diagnostic output formatting and add evidence structure

* feat: implement attack surface ranking for diagnostics with scoring and sorting

* feat: add comprehensive documentation for installation, usage, and rules reference

* feat: add multiple language support for command execution and evaluation endpoints

* feat: implement inline suppression for findings using `nyx:ignore` comments

* feat: add confidence levels to AST patterns and update output structure

* feat: implement low-noise prioritization system with category filtering, rollup grouping, and configurable budgets

* feat: bump version to 0.4.0 and update changelog with new features and improvements

* feat: add dead code allowances to various functions in mod.rs and real_world_tests.rs
2026-02-25 21:16:36 -05:00

4.2 KiB

JavaScript Rules

JavaScript has the most complete taint label coverage alongside Rust. Nyx detects code execution, XSS, prototype pollution, command injection, and weak crypto.

Taint Sources

Function Capability Source Kind
document.location, window.location all UserInput
req.body, req.query, req.params all UserInput
req.headers, req.cookies all UserInput
process.env all EnvironmentConfig

Taint Sinks

Function Required Capability
eval SHELL_ESCAPE
innerHTML HTML_ESCAPE
location.href, window.location.href URL_ENCODE
child_process.exec, child_process.execSync SHELL_ESCAPE
child_process.spawn SHELL_ESCAPE

Taint Sanitizers

Function Strips Capability
JSON.parse JSON_PARSE
encodeURIComponent, encodeURI URL_ENCODE
DOMPurify.sanitize HTML_ESCAPE

Note: Anonymous function expressions and arrow functions passed as callback arguments (e.g., Express app.get('/path', function(req, res) { ... })) are automatically walked as separate function scopes for taint analysis. Each anonymous function gets a unique scope identifier to prevent cross-function taint leakage.


AST Pattern Rules

Code Execution

Rule ID Severity Tier Description
js.code_exec.eval High A eval() — dynamic code execution
js.code_exec.new_function High A new Function() — eval equivalent
js.code_exec.settimeout_string Medium A setTimeout/setInterval with string argument

XSS Sinks

Rule ID Severity Tier Description
js.xss.document_write Medium A document.write() / document.writeln()
js.xss.outer_html Medium A Assignment to .outerHTML
js.xss.insert_adjacent_html Medium A insertAdjacentHTML()
js.xss.location_assign Medium A Assignment to location/location.href — open redirect
js.xss.cookie_write Medium A Write to document.cookie

Prototype Pollution

Rule ID Severity Tier Description
js.prototype.proto_assignment Medium A Assignment to __proto__
js.prototype.extend_object Medium A Assignment to Object.prototype.*

Weak Crypto

Rule ID Severity Tier Description
js.crypto.weak_hash Low A crypto.createHash("md5"/"sha1")
js.crypto.math_random Low A Math.random() — not cryptographically secure

Insecure Transport

Rule ID Severity Tier Description
js.transport.fetch_http Low A fetch("http://...") — plaintext HTTP

Examples

js.code_exec.eval — Dynamic code execution

Vulnerable:

const code = req.query.code;
eval(code);  // Remote code execution

Safe alternative:

// Use a sandboxed interpreter or avoid eval entirely
const allowed = { add: (a, b) => a + b };
const result = allowed[req.query.operation]?.(req.query.a, req.query.b);

js.xss.document_write — XSS sink

Vulnerable:

document.write("<h1>" + userName + "</h1>");

Safe alternative:

const el = document.createElement("h1");
el.textContent = userName;
document.body.appendChild(el);

js.prototype.proto_assignment — Prototype pollution

Vulnerable:

function merge(target, source) {
    for (let key in source) {
        target[key] = source[key];  // If key is "__proto__", pollutes prototype
    }
}

Safe alternative:

function merge(target, source) {
    for (let key in source) {
        if (key === "__proto__" || key === "constructor") continue;
        target[key] = source[key];
    }
}

Taint: req.bodyeval()

Finding:

[HIGH]   taint-unsanitised-flow (source 2:18)  src/handler.js:3:5
         Source: req.body at 2:18
         Sink: eval()
         Score: 78