mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-30 20:39:39 +02:00
[pitboss/grind] cleanup session-0012 (20260521T201327Z-3848)
This commit is contained in:
parent
3c427436aa
commit
ca4349ded5
10 changed files with 25 additions and 63 deletions
|
|
@ -119,7 +119,7 @@ Each line is a JSON object with a versioned envelope:
|
||||||
{
|
{
|
||||||
"schema_version": 1,
|
"schema_version": 1,
|
||||||
"nyx_version": "0.7.0",
|
"nyx_version": "0.7.0",
|
||||||
"corpus_version": "4",
|
"corpus_version": "15",
|
||||||
"kind": "verdict",
|
"kind": "verdict",
|
||||||
"ts": "2026-05-15T18:42:09Z",
|
"ts": "2026-05-15T18:42:09Z",
|
||||||
"finding_id": "a3b1...",
|
"finding_id": "a3b1...",
|
||||||
|
|
@ -134,6 +134,8 @@ Each line is a JSON object with a versioned envelope:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The literal `nyx_version` and `corpus_version` values shift between releases; see `crate::dynamic::telemetry::CORPUS_VERSION` for the active payload-corpus version your binary writes.
|
||||||
|
|
||||||
| Field | Meaning |
|
| Field | Meaning |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `schema_version` | Event schema version. Readers reject mismatches. |
|
| `schema_version` | Event schema version. Readers reject mismatches. |
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ Human-readable, color-coded output to stdout. Status messages go to stderr.
|
||||||
|
|
||||||
| Tag | Color | Meaning |
|
| Tag | Color | Meaning |
|
||||||
|-----|-------|---------|
|
|-----|-------|---------|
|
||||||
| `[HIGH]` | Red, bold | Critical -- likely exploitable |
|
| `[HIGH]` | Red, bold | Critical, likely exploitable |
|
||||||
| `[MEDIUM]` | Orange, bold | Important -- may be exploitable |
|
| `[MEDIUM]` | Orange, bold | Important, may be exploitable |
|
||||||
| `[LOW]` | Muted blue-gray | Informational -- code quality or weak signal |
|
| `[LOW]` | Muted blue-gray | Informational: code quality or weak signal |
|
||||||
|
|
||||||
### Evidence fields
|
### Evidence fields
|
||||||
|
|
||||||
|
|
@ -139,9 +139,9 @@ Fields marked "no" are omitted when empty/null/false to keep output compact.
|
||||||
|
|
||||||
| Level | Meaning |
|
| Level | Meaning |
|
||||||
|-------|---------|
|
|-------|---------|
|
||||||
| `High` | Strong signal -- taint-confirmed flow, definite state violation |
|
| `High` | Strong signal: taint-confirmed flow, definite state violation |
|
||||||
| `Medium` | Moderate signal -- resource leak, path-validated taint, CFG structural |
|
| `Medium` | Moderate signal: resource leak, path-validated taint, CFG structural |
|
||||||
| `Low` | Weak signal -- AST pattern match, possible resource leak, degraded analysis |
|
| `Low` | Weak signal: AST pattern match, possible resource leak, degraded analysis |
|
||||||
|
|
||||||
### Evidence object
|
### Evidence object
|
||||||
|
|
||||||
|
|
@ -192,12 +192,12 @@ nyx scan . --format sarif > results.sarif
|
||||||
|
|
||||||
The SARIF output includes:
|
The SARIF output includes:
|
||||||
|
|
||||||
- **Tool metadata** -- Nyx name and version
|
- **Tool metadata**: Nyx name and version
|
||||||
- **Rules** -- Rule ID, description, severity mapping
|
- **Rules**: Rule ID, description, severity mapping
|
||||||
- **Results** -- One result per finding with location, message, and properties
|
- **Results**: One result per finding with location, message, and properties
|
||||||
- **Properties** -- Each result includes `category` and optionally `confidence` and `rollup.count`
|
- **Properties**: Each result includes `category` and optionally `confidence` and `rollup.count`
|
||||||
- **Related locations** -- Rollup findings include example locations in `relatedLocations`
|
- **Related locations**: Rollup findings include example locations in `relatedLocations`
|
||||||
- **Artifacts** -- File paths referenced by findings
|
- **Artifacts**: File paths referenced by findings
|
||||||
|
|
||||||
### GitHub Code Scanning integration
|
### GitHub Code Scanning integration
|
||||||
|
|
||||||
|
|
@ -219,9 +219,10 @@ The SARIF output includes:
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `0` | Scan completed successfully; no findings matched `--fail-on` threshold |
|
| `0` | Scan completed successfully; no findings matched `--fail-on` threshold |
|
||||||
| `1` | `--fail-on` threshold breached (at least one finding meets or exceeds the specified severity) |
|
| `1` | `--fail-on` threshold breached (at least one finding meets or exceeds the specified severity) |
|
||||||
| Non-zero | Error (I/O, config, database, parse error) |
|
| `2` | `--gate` policy tripped (e.g. `no-new-confirmed` saw a new Confirmed finding, or `resolve-all-confirmed` saw a previously Confirmed finding still open) |
|
||||||
|
| Other non-zero | Error (I/O, config, database, parse error) |
|
||||||
|
|
||||||
Without `--fail-on`, Nyx always exits `0` on a successful scan regardless of findings count.
|
Without `--fail-on` or `--gate`, Nyx always exits `0` on a successful scan regardless of findings count.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -229,9 +230,9 @@ Without `--fail-on`, Nyx always exits `0` on a successful scan regardless of fin
|
||||||
|
|
||||||
| Level | Description | Typical rules |
|
| Level | Description | Typical rules |
|
||||||
|-------|-------------|---------------|
|
|-------|-------------|---------------|
|
||||||
| **High** | Critical vulnerabilities -- likely exploitable | Command injection, unsafe deserialization, banned C functions, taint-confirmed flows with user input sources |
|
| **High** | Critical vulnerabilities, likely exploitable | Command injection, unsafe deserialization, banned C functions, taint-confirmed flows with user input sources |
|
||||||
| **Medium** | Important issues -- may be exploitable with additional context | SQL concatenation, XSS sinks, reflection, unguarded sinks, resource leaks |
|
| **Medium** | Important issues, may be exploitable with additional context | SQL concatenation, XSS sinks, reflection, unguarded sinks, resource leaks |
|
||||||
| **Low** | Informational -- code quality or weak signals | Weak crypto algorithms, insecure randomness, `unwrap()`/`panic!()`, type-safety escapes |
|
| **Low** | Informational: code quality or weak signals | Weak crypto algorithms, insecure randomness, `unwrap()`/`panic!()`, type-safety escapes |
|
||||||
|
|
||||||
### Non-production severity downgrade
|
### Non-production severity downgrade
|
||||||
|
|
||||||
|
|
@ -260,13 +261,13 @@ Suppress specific findings directly in source code using `nyx:ignore` comments.
|
||||||
### Directive forms
|
### Directive forms
|
||||||
|
|
||||||
```python
|
```python
|
||||||
x = dangerous() # nyx:ignore taint-unsanitised-flow ← suppresses this line
|
x = dangerous() # nyx:ignore taint-unsanitised-flow (suppresses this line)
|
||||||
# nyx:ignore-next-line taint-unsanitised-flow
|
# nyx:ignore-next-line taint-unsanitised-flow
|
||||||
x = dangerous() ← suppresses this line
|
x = dangerous() (suppressed by the comment above)
|
||||||
```
|
```
|
||||||
|
|
||||||
- `nyx:ignore <RULE_ID>` -- suppresses findings on the **same line** as the comment.
|
- `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**.
|
- `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).
|
- For taint findings, the primary line is the **sink line** (the `line` field in output).
|
||||||
|
|
||||||
### Rule ID matching
|
### Rule ID matching
|
||||||
|
|
|
||||||
|
|
@ -1893,7 +1893,6 @@ impl<'a> ParsedFile<'a> {
|
||||||
cfg: &body.graph,
|
cfg: &body.graph,
|
||||||
entry: body.entry,
|
entry: body.entry,
|
||||||
lang: caller_lang,
|
lang: caller_lang,
|
||||||
file_path: &self.source.file_path_str,
|
|
||||||
source_bytes: self.source.bytes,
|
source_bytes: self.source.bytes,
|
||||||
func_summaries: self.local_summaries(),
|
func_summaries: self.local_summaries(),
|
||||||
global_summaries,
|
global_summaries,
|
||||||
|
|
|
||||||
|
|
@ -157,10 +157,6 @@ fn find_auth_nodes(ctx: &AnalysisContext) -> Vec<NodeIndex> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CfgAnalysis for AuthGap {
|
impl CfgAnalysis for AuthGap {
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"auth-gap"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
||||||
// Decorator/annotation/attribute auth on the body declaration
|
// Decorator/annotation/attribute auth on the body declaration
|
||||||
// already gates every sink in the body, skip the
|
// already gates every sink in the body, skip the
|
||||||
|
|
@ -218,7 +214,6 @@ impl CfgAnalysis for AuthGap {
|
||||||
|
|
||||||
findings.push(CfgFinding {
|
findings.push(CfgFinding {
|
||||||
rule_id: "cfg-auth-gap".to_string(),
|
rule_id: "cfg-auth-gap".to_string(),
|
||||||
title: "Missing auth check".to_string(),
|
|
||||||
severity: Severity::High,
|
severity: Severity::High,
|
||||||
confidence: Confidence::Medium,
|
confidence: Confidence::Medium,
|
||||||
span: info.ast.span,
|
span: info.ast.span,
|
||||||
|
|
|
||||||
|
|
@ -306,10 +306,6 @@ fn find_post_if_sinks(cfg: &crate::cfg::Cfg, if_node: NodeIndex) -> Vec<NodeInde
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CfgAnalysis for IncompleteErrorHandling {
|
impl CfgAnalysis for IncompleteErrorHandling {
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"incomplete-error-handling"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
||||||
let mut findings = Vec::new();
|
let mut findings = Vec::new();
|
||||||
|
|
||||||
|
|
@ -369,7 +365,6 @@ impl CfgAnalysis for IncompleteErrorHandling {
|
||||||
if has_dangerous_successor {
|
if has_dangerous_successor {
|
||||||
findings.push(CfgFinding {
|
findings.push(CfgFinding {
|
||||||
rule_id: "cfg-error-fallthrough".to_string(),
|
rule_id: "cfg-error-fallthrough".to_string(),
|
||||||
title: "Error check without return".to_string(),
|
|
||||||
severity: Severity::Medium,
|
severity: Severity::Medium,
|
||||||
confidence: Confidence::Medium,
|
confidence: Confidence::Medium,
|
||||||
span: info.ast.span,
|
span: info.ast.span,
|
||||||
|
|
|
||||||
|
|
@ -2715,10 +2715,6 @@ fn sink_in_entrypoint(ctx: &AnalysisContext, sink: NodeIndex) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CfgAnalysis for UnguardedSink {
|
impl CfgAnalysis for UnguardedSink {
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"unguarded-sink"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
||||||
let doms = dominators::compute_dominators(ctx.cfg, ctx.entry);
|
let doms = dominators::compute_dominators(ctx.cfg, ctx.entry);
|
||||||
let sink_nodes = dominators::find_sink_nodes(ctx.cfg);
|
let sink_nodes = dominators::find_sink_nodes(ctx.cfg);
|
||||||
|
|
@ -2976,7 +2972,6 @@ impl CfgAnalysis for UnguardedSink {
|
||||||
|
|
||||||
findings.push(CfgFinding {
|
findings.push(CfgFinding {
|
||||||
rule_id: "cfg-unguarded-sink".to_string(),
|
rule_id: "cfg-unguarded-sink".to_string(),
|
||||||
title: "Unguarded sink".to_string(),
|
|
||||||
severity,
|
severity,
|
||||||
confidence,
|
confidence,
|
||||||
span: sink_info.ast.span,
|
span: sink_info.ast.span,
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,6 @@ pub enum Confidence {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CfgFinding {
|
pub struct CfgFinding {
|
||||||
pub rule_id: String,
|
pub rule_id: String,
|
||||||
#[allow(dead_code)]
|
|
||||||
pub title: String,
|
|
||||||
pub severity: Severity,
|
pub severity: Severity,
|
||||||
pub confidence: Confidence,
|
pub confidence: Confidence,
|
||||||
pub span: (usize, usize),
|
pub span: (usize, usize),
|
||||||
|
|
@ -154,12 +152,8 @@ pub struct AnalysisContext<'a> {
|
||||||
pub cfg: &'a crate::cfg::Cfg,
|
pub cfg: &'a crate::cfg::Cfg,
|
||||||
pub entry: NodeIndex,
|
pub entry: NodeIndex,
|
||||||
pub lang: Lang,
|
pub lang: Lang,
|
||||||
#[allow(dead_code)]
|
|
||||||
pub file_path: &'a str,
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub source_bytes: &'a [u8],
|
pub source_bytes: &'a [u8],
|
||||||
pub func_summaries: &'a FuncSummaries,
|
pub func_summaries: &'a FuncSummaries,
|
||||||
#[allow(dead_code)]
|
|
||||||
pub global_summaries: Option<&'a GlobalSummaries>,
|
pub global_summaries: Option<&'a GlobalSummaries>,
|
||||||
/// Per-file SSA summaries map produced by
|
/// Per-file SSA summaries map produced by
|
||||||
/// `lower_all_functions_from_bodies` (after both the augment pass
|
/// `lower_all_functions_from_bodies` (after both the augment pass
|
||||||
|
|
@ -170,7 +164,6 @@ pub struct AnalysisContext<'a> {
|
||||||
/// suppress structural findings whose taint flow has been proven
|
/// suppress structural findings whose taint flow has been proven
|
||||||
/// validated through helper summaries (CVE-2026-25544 patched
|
/// validated through helper summaries (CVE-2026-25544 patched
|
||||||
/// counterpart).
|
/// counterpart).
|
||||||
#[allow(dead_code)]
|
|
||||||
pub ssa_summaries: Option<
|
pub ssa_summaries: Option<
|
||||||
&'a std::collections::HashMap<
|
&'a std::collections::HashMap<
|
||||||
crate::symbol::FuncKey,
|
crate::symbol::FuncKey,
|
||||||
|
|
@ -218,8 +211,6 @@ pub struct AnalysisContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CfgAnalysis {
|
pub trait CfgAnalysis {
|
||||||
#[allow(dead_code)]
|
|
||||||
fn name(&self) -> &'static str;
|
|
||||||
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding>;
|
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -531,10 +531,6 @@ fn has_explicit_lock_acquire(ctx: &AnalysisContext, acquire: NodeIndex) -> bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CfgAnalysis for ResourceMisuse {
|
impl CfgAnalysis for ResourceMisuse {
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"resource-misuse"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
||||||
let pairs = rules::resource_pairs(ctx.lang);
|
let pairs = rules::resource_pairs(ctx.lang);
|
||||||
let exit = match dominators::find_exit_node(ctx.cfg) {
|
let exit = match dominators::find_exit_node(ctx.cfg) {
|
||||||
|
|
@ -631,7 +627,6 @@ impl CfgAnalysis for ResourceMisuse {
|
||||||
} else {
|
} else {
|
||||||
"cfg-resource-leak".to_string()
|
"cfg-resource-leak".to_string()
|
||||||
},
|
},
|
||||||
title: format!("{} may leak", pair.resource_name),
|
|
||||||
severity: Severity::Medium,
|
severity: Severity::Medium,
|
||||||
confidence: Confidence::Medium,
|
confidence: Confidence::Medium,
|
||||||
span: info.ast.span,
|
span: info.ast.span,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ fn parse_and_analyse<A: CfgAnalysis>(
|
||||||
cfg,
|
cfg,
|
||||||
entry,
|
entry,
|
||||||
lang,
|
lang,
|
||||||
file_path: "test.rs",
|
|
||||||
source_bytes: src,
|
source_bytes: src,
|
||||||
func_summaries: summaries,
|
func_summaries: summaries,
|
||||||
global_summaries: None,
|
global_summaries: None,
|
||||||
|
|
@ -54,7 +53,6 @@ fn parse_and_run_all(src: &[u8], lang_str: &str, ts_lang: Language) -> Vec<CfgFi
|
||||||
cfg,
|
cfg,
|
||||||
entry,
|
entry,
|
||||||
lang,
|
lang,
|
||||||
file_path: "test.rs",
|
|
||||||
source_bytes: src,
|
source_bytes: src,
|
||||||
func_summaries: summaries,
|
func_summaries: summaries,
|
||||||
global_summaries: None,
|
global_summaries: None,
|
||||||
|
|
@ -90,7 +88,6 @@ fn parse_and_run_all_with_taint(
|
||||||
cfg,
|
cfg,
|
||||||
entry,
|
entry,
|
||||||
lang,
|
lang,
|
||||||
file_path: "test.rs",
|
|
||||||
source_bytes: src,
|
source_bytes: src,
|
||||||
func_summaries: summaries,
|
func_summaries: summaries,
|
||||||
global_summaries: None,
|
global_summaries: None,
|
||||||
|
|
@ -210,7 +207,6 @@ fn parse_and_analyse_with_ssa<A: CfgAnalysis>(
|
||||||
cfg: &body.graph,
|
cfg: &body.graph,
|
||||||
entry: body.entry,
|
entry: body.entry,
|
||||||
lang,
|
lang,
|
||||||
file_path: "test.rs",
|
|
||||||
source_bytes: src,
|
source_bytes: src,
|
||||||
func_summaries: &file_cfg.summaries,
|
func_summaries: &file_cfg.summaries,
|
||||||
global_summaries: None,
|
global_summaries: None,
|
||||||
|
|
@ -1227,7 +1223,6 @@ fn config_sanitizer_suppresses_unguarded_sink() {
|
||||||
cfg,
|
cfg,
|
||||||
entry,
|
entry,
|
||||||
lang,
|
lang,
|
||||||
file_path: "test.rs",
|
|
||||||
source_bytes: src,
|
source_bytes: src,
|
||||||
func_summaries: summaries,
|
func_summaries: summaries,
|
||||||
global_summaries: None,
|
global_summaries: None,
|
||||||
|
|
@ -1708,7 +1703,6 @@ fn cfg_only_no_taint_produces_low_severity() {
|
||||||
cfg,
|
cfg,
|
||||||
entry,
|
entry,
|
||||||
lang,
|
lang,
|
||||||
file_path: "test.rs",
|
|
||||||
source_bytes: src,
|
source_bytes: src,
|
||||||
func_summaries: summaries,
|
func_summaries: summaries,
|
||||||
global_summaries: None,
|
global_summaries: None,
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,6 @@ fn event_handler_callbacks(ctx: &AnalysisContext) -> HashSet<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CfgAnalysis for UnreachableCode {
|
impl CfgAnalysis for UnreachableCode {
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
"unreachable-code"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
fn run(&self, ctx: &AnalysisContext) -> Vec<CfgFinding> {
|
||||||
let reachable = dominators::reachable_set(ctx.cfg, ctx.entry);
|
let reachable = dominators::reachable_set(ctx.cfg, ctx.entry);
|
||||||
let handler_callbacks = event_handler_callbacks(ctx);
|
let handler_callbacks = event_handler_callbacks(ctx);
|
||||||
|
|
@ -122,7 +118,6 @@ impl CfgAnalysis for UnreachableCode {
|
||||||
|
|
||||||
findings.push(CfgFinding {
|
findings.push(CfgFinding {
|
||||||
rule_id: rule_id.to_string(),
|
rule_id: rule_id.to_string(),
|
||||||
title: title.to_string(),
|
|
||||||
severity,
|
severity,
|
||||||
confidence: Confidence::High,
|
confidence: Confidence::High,
|
||||||
span: info.ast.span,
|
span: info.ast.span,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue