Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Output Formats

Nyx supports three output formats, selected with --format or output.default_format in config.

Console (default)

Human-readable, color-coded output to stdout. Status messages go to stderr.

[HIGH]   taint-unsanitised-flow (source 5:11)  src/handler.rs:12:5 (Score: 76, Confidence: High)
         Source: env::var("CMD") → Command::new("sh").arg("-c")

[MEDIUM] cfg-unguarded-sink                    src/handler.rs:12:5 (Score: 35, Confidence: Medium)

[LOW]    rs.quality.unwrap                     src/lib.rs:88:5 (Score: 10, Confidence: High)

Severity indicators

TagColorMeaning
[HIGH]Red, boldCritical – likely exploitable
[MEDIUM]Orange, boldImportant – may be exploitable
[LOW]Muted blue-grayInformational – code quality or weak signal

Evidence fields

Taint and state findings include structured evidence:

LabelMeaning
SourceWhere tainted data originated (function name + location)
SinkWhere the dangerous operation happens
Path guardType of validation predicate protecting the path

Score

When attack-surface ranking is enabled (default), each finding shows a Score value. Higher scores indicate greater exploitability. See Detector Overview for the scoring formula.

Rollup findings

High-frequency LOW Quality findings (e.g. rs.quality.unwrap) are grouped into rollup findings by (file, rule):

  21:10  ● [LOW]   rs.quality.unwrap
      rs.quality.unwrap (38 occurrences)
      Examples: 21:10, 50:10, 79:10, 105:10, 134:10
      Run: nyx scan --show-instances rs.quality.unwrap

Rollups count as one finding for LOW budget enforcement. Use --show-instances <RULE> to expand a specific rule or --all to disable rollups entirely.

When findings are suppressed by the prioritization pipeline, a footer is shown:

Suppressed 195 LOW/Quality findings.
Active filters:
  include_quality = false
  max_low = 20
  max_low_per_file = 1
  max_low_per_rule = 10

Use --include-quality, --max-low, or --all to adjust.

JSON

Machine-readable JSON array. Each finding is an object:

[
  {
    "path": "src/handler.rs",
    "line": 12,
    "col": 5,
    "severity": "High",
    "id": "taint-unsanitised-flow (source 5:11)",
    "path_validated": false,
    "labels": [
      ["Source", "env::var(\"CMD\") at 5:11"],
      ["Sink", "Command::new(\"sh\").arg(\"-c\")"]
    ],
    "confidence": "High",
    "evidence": {
      "source": {
        "path": "src/handler.rs",
        "line": 5,
        "col": 11,
        "kind": "source",
        "snippet": "env::var(\"CMD\")"
      },
      "sink": {
        "path": "src/handler.rs",
        "line": 12,
        "col": 5,
        "kind": "sink",
        "snippet": "Command::new(\"sh\")"
      },
      "notes": ["source_kind:EnvironmentConfig"]
    },
    "rank_score": 76.0,
    "rank_reason": [
      ["severity_base", "60"],
      ["analysis_kind", "10"],
      ["source_kind", "5"],
      ["evidence_count", "1"]
    ]
  }
]

Field descriptions

FieldTypeAlways presentDescription
pathstringyesFile path relative to scan root
lineintyes1-indexed line number
colintyes1-indexed column number
severitystringyes"High", "Medium", or "Low"
idstringyesRule ID
categorystringyesFinding category: "Security", "Reliability", or "Quality"
path_validatedboolnoTrue if guarded by validation predicate
guard_kindstringnoPredicate type (e.g. "NullCheck", "ValidationCall")
messagestringnoHuman-readable context (state analysis findings)
labelsarraynoArray of [label, value] pairs for console display
confidencestringnoConfidence level: "Low", "Medium", or "High"
evidenceobjectnoStructured evidence (source/sink spans, state, notes)
rank_scorefloatnoAttack-surface score (omitted when ranking disabled)
rank_reasonarraynoScore breakdown (omitted when ranking disabled)
rollupobjectnoRollup data when findings are grouped (see below)

Fields marked “no” are omitted when empty/null/false to keep output compact.

Confidence levels

LevelMeaning
HighStrong signal – taint-confirmed flow, definite state violation
MediumModerate signal – resource leak, path-validated taint, CFG structural
LowWeak signal – AST pattern match, possible resource leak, degraded analysis

Evidence object

The evidence field provides structured provenance data:

FieldTypeDescription
sourceobjectSource span (path, line, col, kind, snippet)
sinkobjectSink span (path, line, col, kind, snippet)
guardsarrayValidation guard spans
sanitizersarraySanitizer spans
stateobjectState-machine evidence (machine, subject, from_state, to_state)
notesarrayFree-form notes (e.g. "source_kind:UserInput", "path_validated")

All fields are omitted when empty/null.

Rollup object

When a finding is a rollup (grouped from multiple occurrences), the rollup field is present:

{
  "rollup": {
    "count": 38,
    "occurrences": [
      { "line": 21, "col": 10 },
      { "line": 50, "col": 10 },
      { "line": 79, "col": 10 }
    ]
  }
}
FieldTypeDescription
countintTotal number of occurrences
occurrencesarrayFirst N example locations (controlled by rollup_examples)

SARIF (Static Analysis Results Interchange Format)

SARIF 2.1.0 JSON, suitable for GitHub Code Scanning and other SARIF-compatible tools.

nyx scan . --format sarif > results.sarif

The SARIF output includes:

  • Tool metadata – Nyx name and version
  • Rules – Rule ID, description, severity mapping
  • Results – One result per finding with location, message, and properties
  • Properties – Each result includes category and optionally confidence and rollup.count
  • Related locations – Rollup findings include example locations in relatedLocations
  • Artifacts – File paths referenced by findings

GitHub Code Scanning integration

- name: Run Nyx
  run: nyx scan . --format sarif > results.sarif

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: results.sarif

Exit Codes

CodeMeaning
0Scan completed successfully; no findings matched --fail-on threshold
1--fail-on threshold breached (at least one finding meets or exceeds the specified severity)
Non-zeroError (I/O, config, database, parse error)

Without --fail-on, Nyx always exits 0 on a successful scan regardless of findings count.


Severity Levels

LevelDescriptionTypical rules
HighCritical vulnerabilities – likely exploitableCommand injection, unsafe deserialization, banned C functions, taint-confirmed flows with user input sources
MediumImportant issues – may be exploitable with additional contextSQL concatenation, XSS sinks, reflection, unguarded sinks, resource leaks
LowInformational – code quality or weak signalsWeak crypto algorithms, insecure randomness, unwrap()/panic!(), type-safety escapes

Non-production severity downgrade

By default, findings in paths matching common non-production patterns (tests/, test/, vendor/, build/, examples/, benchmarks/) are downgraded by one tier:

  • High → Medium
  • Medium → Low
  • Low → Low (unchanged)

Use --keep-nonprod-severity to disable this behavior.


Inline Suppressions

Suppress specific findings directly in source code using nyx:ignore comments. Suppressed findings are excluded from output, severity counts, and --fail-on checks by default.

Comment syntax

LanguageComment styles
Rust, C, C++, Java, Go, JS, TS// nyx:ignore ... or /* nyx:ignore ... */
Python, Ruby# nyx:ignore ...
PHP// nyx:ignore ..., # nyx:ignore ..., or /* nyx:ignore ... */

Directive forms

x = dangerous()  # nyx:ignore taint-unsanitised-flow     ← suppresses this line
# nyx:ignore-next-line taint-unsanitised-flow
x = dangerous()                                           ← suppresses this line
  • nyx:ignore <RULE_ID> – suppresses findings on the same line as the comment.
  • nyx:ignore-next-line <RULE_ID> – suppresses findings on the next line.
  • For taint findings, the primary line is the sink line (the line field in output).

Rule ID matching

  • Case-sensitive, exact match after canonicalization.
  • Comma-separated: nyx:ignore rule-a, rule-b
  • Wildcard suffix: nyx:ignore rs.quality.* matches any ID starting with rs.quality.
  • Taint IDs are canonicalized: nyx:ignore taint-unsanitised-flow matches taint-unsanitised-flow (source 5:1) (parenthetical suffix stripped).

Console behavior

  • Default: suppressed findings are hidden entirely.
  • --show-suppressed: suppressed findings appear dimmed with [SUPPRESSED] tag. Summary shows "N issues (M suppressed)".

JSON / SARIF behavior

  • Default: suppressed findings are excluded from JSON/SARIF output.
  • --show-suppressed: suppressed findings are included with additional fields:
{
  "suppressed": true,
  "suppression": {
    "kind": "SameLine",
    "matched_pattern": "taint-unsanitised-flow",
    "directive_line": 42
  }
}

Exit code

Suppressed findings do not trigger --fail-on. A scan with only suppressed findings exits 0.


Rule ID Format

PrefixDetectorExample
taint-*Taint analysistaint-unsanitised-flow (source 5:11)
cfg-*CFG structuralcfg-unguarded-sink, cfg-auth-gap
state-*State modelstate-use-after-close, state-resource-leak
<lang>.*.*AST patternsrs.memory.transmute, js.code_exec.eval

See the Rule Reference for a complete listing.