# -------------------------------------------------------------------- # nyx Vulnerability Scanner — DEFAULT CONFIGURATION # # Copy this file to `nyx.local` in the same directory and override # only the keys you need. Anything you omit inherits the defaults # shown here. # -------------------------------------------------------------------- [scanner] ## Analysis mode: full | ast | cfg | taint ## full = AST analyses + CFG + state + taint ## ast = AST analyses only (tree-sitter patterns + auth analysis; no CFG/taint/state) ## cfg = CFG + state + taint only (no AST patterns) ## taint = taint-focused CFG analysis only (no AST patterns, no state findings) mode = "full" ## Minimum severity level to include in the report ## Possible values: Low | Medium | High min_severity = "Low" ## Maximum file size to scan (MiB); null = unlimited. ## Raise or set to `null` when scanning a trusted codebase with large generated files or bundles. max_file_size_mb = 16 ## File extensions to ignore completely excluded_extensions = [ "jpg", "png", "gif", "mp4", "avi", "mkv", "zip", "tar", "gz", "exe", "dll", "so", ] ## Directories to ignore completely excluded_directories = [ "node_modules", ".git", "target", ".vscode", ".idea", "build", "dist", ] ## Individual files to ignore completely excluded_files = [] ## Honour global ignore file (e.g. ~/.config/nyx/ignore) (RESERVED) read_global_ignore = false ## Honour .gitignore / .hgignore, etc. read_vcsignore = true ## Require a .git directory to read gitignore files require_git_to_read_vcsignore = true ## Limit search to the starting file system only one_file_system = false ## Follow symlinks when scanning follow_symlinks = false ## Scan hidden files (dot-files) scan_hidden_files = false ## Enable state-model dataflow analysis (resource lifecycle + auth state). ## Detects use-after-close, double-close, resource leaks, and unauthed access. ## Requires mode = "full" or "cfg" (or explicit taint/state-capable scans). Default: on. enable_state_analysis = true ## Enable AST-based authorization analysis for supported web frameworks. ## Produces `.auth.*` findings such as admin-route, ownership, token, ## and stale-auth checks. Runs only when AST analysis is active: ## mode = "full" or "ast" => auth analysis runs ## mode = "cfg" or "taint" => auth analysis is skipped ## Per-language auth overrides live under [analysis.languages..auth]. enable_auth_analysis = true ## Run dynamic verification on Medium/High confidence findings after static analysis. ## Default builds include this support. Use --no-verify or set this false for ## fast static-only scans, or when building with --no-default-features. verify = true ## Also verify Low-confidence findings. Slower; intended for payload tuning. verify_all_confidence = false ## Dynamic sandbox backend: auto | docker | process | firecracker ## auto uses Docker when available, otherwise the process backend. verify_backend = "auto" ## Process-backend hardening profile: standard | strict harden_profile = "standard" ## Catch per-file panics during analysis and continue the scan. ## When false (default), a panic in one file's analyser aborts the whole ## scan — useful for catching engine bugs loudly in development. ## When true, the poisoned file is skipped with a warning; the rest of ## the scan proceeds. Enable when running against untrusted input. # enable_panic_recovery = false [database] ## Custom SQLite database path (empty = platform default) (RESERVED) path = "" ## Number of days to keep database files; 0 = no cleanup (RESERVED) auto_cleanup_days = 30 ## Maximum database size in MiB; 0 = no limit (RESERVED) max_db_size_mb = 1024 ## Run VACUUM on startup vacuum_on_startup = false [output] ## Default output format: console | json | sarif ## Used when --format is not specified on the command line. default_format = "console" ## Suppress all human-readable status output (stderr) quiet = false ## Enable attack-surface ranking (sort findings by exploitability score) attack_surface_ranking = true ## Cap the number of issues shown; null = unlimited max_results = null ## Minimum attack-surface score to include; null = no minimum ## Findings below this threshold are dropped after ranking. ## Requires attack_surface_ranking to be enabled. min_score = null ## Minimum confidence level to include in output; null = no minimum ## Values: "low", "medium", "high" # min_confidence = "medium" ## Include Quality-category findings (excluded by default). ## Quality findings (e.g. unwrap, expect, panic) are noise-heavy and hidden ## unless this is set to true or --include-quality is passed. include_quality = false ## Show all findings: disables category filtering, rollups, and LOW budgets. ## Equivalent to --all on the command line. show_all = false ## Maximum total LOW findings to show (rollups count as 1). max_low = 20 ## Maximum LOW findings per file (rollups count as 1). max_low_per_file = 1 ## Maximum LOW findings per rule (rollups count as 1). max_low_per_rule = 10 ## Number of example locations stored in rollup findings. rollup_examples = 5 [performance] ## Maximum search depth; null = unlimited max_depth = null ## Minimum depth for reported entries; null = none (RESERVED) min_depth = null ## Stop traversing into matching directories (RESERVED) prune = false ## Worker threads; null or 0 = auto worker_threads = null ## Number of entries to index in a single chunk batch_size = 100 ## Channel capacity multiplier (capacity = threads × this) channel_multiplier = 4 ## Maximum stack size for Rayon threads (bytes) rayon_thread_stack_size = 8388608 # 8 MiB ## Timeout on individual files (seconds); null = none (RESERVED) scan_timeout_secs = null ## Maximum memory to use in MiB; 0 = no limit (RESERVED) memory_limit_mb = 512 [server] ## Enable the local web UI server (nyx serve) enabled = true ## Host to bind to (localhost only by default for security) host = "127.0.0.1" ## Port for the web UI port = 9700 ## Open browser automatically when serve starts open_browser = true ## Auto-reload UI when scan results change auto_reload = true ## Persist scan runs for history view persist_runs = true ## Maximum number of saved runs max_saved_runs = 50 ## Auto-sync triage decisions to .nyx/triage.json in the project root. ## When enabled, triage changes are written to this file so they can be ## committed to git and shared with your team. triage_sync = true [runs] ## Persist scan run history to disk persist = false ## Maximum number of runs to keep max_runs = 100 ## Save scan logs with each run save_logs = false ## Save stdout capture with each run save_stdout = false ## Save code snippets in findings save_code_snippets = true # ─── Scan Profiles ────────────────────────────────────────────────── # Named presets that override scan-related config. # Activate with --profile on the command line. # # Built-in profiles: quick, full, ci, taint_only, conservative_large_repo. # Override a built-in by defining [profiles.] here. # # [profiles.quick] # mode = "ast" # min_severity = "Medium" # # [profiles.ci] # mode = "full" # min_severity = "Medium" # quiet = true # default_format = "sarif" # ─── Analysis engine toggles ──────────────────────────────────────── # Release-grade switches for optional analysis passes. Every field has a # matching CLI flag (e.g. --no-symex / --backwards-analysis), which takes # precedence over the config value for a single run. The listed env vars # override both config and CLI when set to "0" or "false". # # For a shortcut that sets the full stack in one shot, use # `nyx scan --engine-profile {fast,balanced,deep}`. The profile applies # before individual toggles, so you can mix (e.g. `--engine-profile fast # --backwards-analysis`). See `docs/cli.md` for profile contents. # # To print the resolved engine config for a given invocation without # running a scan, pass `--explain-engine`. [analysis.engine] ## Path-constraint solving (prunes infeasible paths in taint). ## Default: on. CLI: --constraint-solving / --no-constraint-solving. ## env: NYX_CONSTRAINT=0 disables. constraint_solving = true ## Abstract interpretation (interval / string domains). ## Default: on. CLI: --abstract-interp / --no-abstract-interp. ## env: NYX_ABSTRACT_INTERP=0 disables. abstract_interpretation = true ## k=1 context-sensitive callee inlining for intra-file calls. ## Default: on. CLI: --context-sensitive / --no-context-sensitive. ## env: NYX_CONTEXT_SENSITIVE=0 disables. context_sensitive = true ## Demand-driven backwards taint analysis. Adds a second pass from ## candidate sinks back toward sources to recover flows the forward ## solver gave up on. Default: off because it adds scan time on large ## repos. CLI: --backwards-analysis / --no-backwards-analysis. ## env: NYX_BACKWARDS=1 enables. backwards_analysis = false ## Per-file tree-sitter parse timeout (ms). 0 disables the cap. ## CLI: --parse-timeout-ms. env: NYX_PARSE_TIMEOUT_MS. parse_timeout_ms = 10000 [analysis.engine.symex] ## Run the symex pipeline after taint. Produces witness strings and ## symbolic verdicts; disable only if you want raw taint output. ## Default: on. CLI: --symex / --no-symex. env: NYX_SYMEX=0 disables. enabled = true ## Persist and consult cross-file SSA bodies so symex can reason about ## callees defined in other files. Adds index/DB work on pass 1. ## Default: on. CLI: --cross-file-symex / --no-cross-file-symex. ## env: NYX_CROSS_FILE_SYMEX=0 disables. cross_file = true ## Intra-file interprocedural symex (k >= 2 via frame stack). ## Default: on. CLI: --symex-interproc / --no-symex-interproc. ## env: NYX_SYMEX_INTERPROC=0 disables. interprocedural = true ## Use the SMT backend when nyx was built with the `smt` feature. ## Ignored when the feature is off. ## Default: on. CLI: --smt / --no-smt. env: NYX_SMT=0 disables. smt = true # ─── Detector knobs ────────────────────────────────────────────────── # Per-detector class suppression and enablement. These knobs target # common false-positive classes that show up on legitimate forwarding # pipelines (telemetry / analytics / metrics dispatch). # # [detectors.data_exfil] # # # Toggle the entire `taint-data-exfiltration` detector class. Set to # # false on projects whose architecture routes user-derived payloads # # through trusted forwarding boundaries by design. # enabled = true # # # URL prefixes treated as trusted destinations. Outbound calls whose # # destination argument has a static prefix (proven by the abstract # # string domain or visible as a literal) matching one of these entries # # have `Cap::DATA_EXFIL` dropped before event emission. Mirrors the # # SSRF prefix-lock semantics. Use full origins or origin-prefixed # # paths (e.g. "https://api.internal/") so partial matches across # # unrelated hosts cannot occur. # trusted_destinations = [ # "https://api.internal/", # "https://telemetry.", # ] # ─── Per-language analysis rules ───────────────────────────────────── # [analysis.languages.javascript.auth] # enabled = true # admin_path_patterns = ["/admin/"] # admin_guard_names = ["requireAdmin", "isAdmin", "adminOnly"] # login_guard_names = ["requireLogin", "authenticate", "requireAuth"] # authorization_check_names = ["checkMembership", "hasWorkspaceMembership", "checkOwnership"] # mutation_indicator_names = ["update", "delete", "create", "archive", "publish", "addMembership"] # read_indicator_names = ["find", "findById", "get", "list"] # token_lookup_names = ["findByToken"] # token_expiry_fields = ["expires_at", "expiresAt"] # token_recipient_fields = ["email", "recipient_email", "recipientEmail"] # Auth-analysis rule IDs use language-normalized prefixes: # javascript + typescript => js.auth.* # python => py.auth.* ruby => rb.auth.* rust => rs.auth.* # TypeScript inherits [analysis.languages.javascript.auth] by default; add an # optional [analysis.languages.typescript.auth] block only for TS-specific # overlays. These settings affect auth analysis only in "full" or "ast" mode. # Add custom sources, sanitizers, sinks, terminators, and event handlers. # Each language is keyed under [analysis.languages.] where slug is # one of: rust, javascript, typescript, python, go, java, c, cpp, php, ruby. # # Example: recognise `escapeHtml` as an HTML sanitizer in JavaScript: # # [analysis.languages.javascript] # event_handlers = ["addEventListener"] # terminators = ["process.exit"] # # [[analysis.languages.javascript.rules]] # matchers = ["escapeHtml"] # kind = "sanitizer" # cap = "html_escape" # # [[analysis.languages.javascript.rules]] # matchers = ["location.href", "window.location.href"] # kind = "sink" # cap = "url_encode" # # Valid `kind` values: "source", "sanitizer", "sink" # Valid `cap` values: "env_var", "html_escape", "shell_escape", # "url_encode", "json_parse", "file_io", # "fmt_string", "sql_query", "deserialize", # "ssrf", "code_exec", "crypto", "all"