Skip to content

Choose a tag to compare

@elicpeter elicpeter released this 29 Apr 07:17
· 45 commits to master since this release
832533a

Nyx 0.5.0

This is the biggest gap between releases since the project started, and most of it shows up under the hood. The taint engine got rewritten on top of an SSA IR. Cross-file analysis is real now, including symbolic execution that walks across file boundaries and produces concrete attack witnesses at sinks. There's a local web UI for triaging findings without leaving your machine.

Heads up: this release rewrites a lot of internals. If you hit a regression or a false positive on a cross-file flow, please open an issue with a minimal repro.

What's new

New taint engine. Block-level worklist over a pruned SSA IR, replaces the old BFS engine across all 10 languages.

Per-body CFGs. Each function, closure, lambda, and callback gets its own CFG with a dedicated entry, exit, and dominator tree, instead of one file-level CFG split at function boundaries. SSA, taint, call-graph keys, and the inline-cache for context sensitivity all key off the body, which is what makes closure analysis and anonymous functions work correctly.

Cross-file analysis. Function summaries persist in SQLite and flow between files. Callee bodies can be loaded and walked, with k=1 context-sensitive inlining for intra-file calls.

Symbolic execution. Candidate findings get walked symbolically from source to sink. Infeasible paths get pruned. Concrete attack strings get reconstructed at sink locations. Optional Z3 backend behind the compile-time smt feature.

Local web UI. nyx serve boots a React frontend on localhost for browsing findings, viewing flow paths, and triaging. Triage decisions write back to .nyx/triage.json so they version with your code.

Tighter false-positive controls. Type-aware sink suppression, abstract interpretation (interval and string-prefix domains), allowlist and type-check guard recognition, confidence scoring on every finding, and a new --require-converged flag for strict CI mode.

Hostile-repo hardening. Path containment checks, loopback-only serving, CSRF tokens for UI mutations, bounded reads on all artifacts. Safe to run on untrusted code.

Detection

Rule-level aggregate F1 is 0.998 (precision 0.995, recall 1.000) on a 433-fixture corpus that includes real CVEs. 0.4.0 was never benchmarked, but the same engine partway through 0.5.0 development scored under 50% recall on a corpus a quarter of the current size, so the lift is large in both directions even though the exact pre/post numbers for 0.4.0 don't exist.

CLI

Analysis-engine toggles graduated from NYX_* env vars to first-class flags and [analysis.engine] config entries: --constraint-solving, --abstract-interp, --context-sensitive, --symex, --cross-file-symex, --symex-interproc, --smt, --parse-timeout-ms, --require-converged. The old env vars still work for library consumers.

Confidence (High / Medium / Low) shows on every finding. Engine notes (UnderReport, OverReport, Bail) surface in console, JSON, and SARIF output. Flow paths are reconstructed step-by-step with file, line, and snippet for each hop.

Cache

SQLite schema bumped to v2. Pre-release versions of 0.5.0 caches get cleared silently on first open. Triage data and scan history are preserved.

Removed

Legacy BFS taint engine and the NYX_LEGACY fallback.

Full changelog: https://github.com/ecpeter23/nyx/blob/master/CHANGELOG.md