mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-18 20:15:14 +02:00
Prerelease cleanup (#46)
* feat: Add const_bound_vars tracking to prevent false positives in ownership checks
* feat: Introduce field interner and typed bounded vars for enhanced type tracking
* feat: Add typed_call_receivers and typed_bounded_dto_fields for enhanced type tracking
* feat: Centralize method name extraction with bare_method_name helper
* feat: Implement Phase-6 hierarchy fan-out for runtime virtual dispatch
* feat: Enhance C++ taint tracking with additional container operations and inline method resolution
* feat: Introduce field-sensitive points-to analysis for enhanced resource tracking
* feat: Implement Pointer-Phase 6 subscript handling for enhanced container analysis
* test: Add comprehensive tests for JavaScript control flow constructs and lattice operations
* docs: Update advanced analysis documentation with field-sensitive points-to and hierarchy fan-out details
* test: Add comprehensive tests for lattice algebra laws and SSA edge cases
* feat: Add destructured session user handling and safe user ID access patterns
* feat: Implement row-population reverse-walk for enhanced authorization checks
* feat: Enhance authorization checks with local alias chain for self-actor types
* feat: Introduce ActiveRecord query safety checks and enhance snippet extraction
* feat: Implement chained method call inner-gate rebinding for SSRF prevention
* feat: Add observability and error modules, enhance debug functionality, and implement theme context
* feat: Remove Auth Analysis page and update navigation to redirect to Explorer
* feat: Optimize SSA lowering by sharing results between taint engine and artifact extractor
* feat: Optimize SSA lowering by sharing results between taint engine and artifact extractor
* feat: Reset path-safe-suppressed spans before lowering to maintain analysis integrity
* fix(ssa): ungate debug_assert_bfs_ordering for release-tests build
The helper at src/ssa/lower.rs was gated `#[cfg(debug_assertions)]` while
the unit test at the bottom of the file was gated only `#[cfg(test)]`.
Since `cfg(test)` is set in release builds with `--tests` but
`cfg(debug_assertions)` is not, `cargo build --release --tests` failed
with E0425. Removing the gate fixes the build; the body is `debug_assert!`
only, so the helper is free in release. Also drop the gate at the call
site to avoid a `dead_code` warning when the lib is built without
`--tests`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(closure-capture): flip JS/TS fixtures to required-finding
The JS and TS closure-capture fixtures pinned the old broken behaviour
via `forbidden_findings: [{ "id_prefix": "taint-" }]`. The engine now
correctly traces taint through the closure boundary (env source captured
by an arrow function, sunk via `child_process.exec` inside the body), so
the formerly-forbidden finding is a true positive.
Match the Python sibling's shape — `required_findings` with
`id_prefix` + `min_count` plus a small `noise_budget` — and rewrite the
companion READMEs and the phase8_fragility_tests doc-comments from
"known gap" to "regression guard".
Verified:
- cargo test --release --test phase8_fragility_tests → 8/8 pass
- cargo test --release --lib bfs_assertion → pass
- corpus benchmark F1 = 0.9976 (TP=205, FP=1, FN=0) — unchanged
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: Add OWASP mapping and baseline mutation hooks for enhanced security analysis
* feat: Introduce health module and enhance health score computation with calibration tests
* feat: Add expectations configuration and cleanup .gitignore for log files
* feat: Implement theme selection and enhance settings panel for triage sync
* feat: Suppress false positives for strcpy calls with literal sources in AST
* feat: Update analyse_function_ssa to return body CFG for accurate analysis
* feat: Add bug report and feature request templates for improved issue tracking
* feat: removed dev scripts
* feat: update README.md for clarity and consistency in fixture descriptions
* feat: removed dev docs
* feat: clean up error handling and UI elements for improved user experience
* feat: adjust button sizes in HeaderBar for better UI consistency
* feat: enhance taint analysis with additional context for sanitizer and taint findings
* cargo fmt
* prettier
* refactor: simplify conditional checks and improve code readability in AST and screenshot capture scripts
* feat: add script to frame PNG screenshots with brand gradient
* feat: add fuzzing support with new targets and CI workflows
* refactor: streamline match expressions and improve formatting in CLI and output handling
* feat: enhance configuration display with detailed output options
* feat: stage demo configuration for improved CLI screenshot output
* feat: expose merge_configs function for user-configurable settings
* refactor: simplify code structure and improve readability in config handling
* refactor: improve descriptions for vulnerability patterns in various languages
* feat: update MIT License section with additional usage details and copyright information
* feat: update screenshots
* refactor: update build process and paths for frontend assets
* feat: add cross-file taint fuzzing target and supporting dictionary
* refactor: clean up formatting and comments in fuzz configuration and example files
* refactor: remove outdated comments and clean up CI configuration files
* chore: update changelog dates and improve formatting in documentation
* refactor: update Cargo.toml and CI configuration for improved packaging and build process
* refactor: enhance quote-stripping logic to prevent panics and add regression tests
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
79c29b394d
commit
82f18184b1
348 changed files with 48731 additions and 2925 deletions
125
src/cli.rs
125
src/cli.rs
|
|
@ -32,6 +32,22 @@ impl Commands {
|
|||
pub fn is_serve(&self) -> bool {
|
||||
matches!(self, Commands::Serve { .. })
|
||||
}
|
||||
|
||||
/// Pure read-only / informational commands that should run without the
|
||||
/// "note: Using …" config preamble or the trailing "Finished in …"
|
||||
/// timing line. These commands' output is often piped or grepped; the
|
||||
/// surrounding chrome is noise.
|
||||
pub fn is_informational(&self) -> bool {
|
||||
match self {
|
||||
Commands::Scan { explain_engine, .. } => *explain_engine,
|
||||
Commands::List { .. } => true,
|
||||
Commands::Config { action } => {
|
||||
matches!(action, ConfigAction::Show { .. } | ConfigAction::Path)
|
||||
}
|
||||
Commands::Index { action } => matches!(action, IndexAction::Status { .. }),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Output format for scan results.
|
||||
|
|
@ -167,11 +183,11 @@ pub enum Commands {
|
|||
path: String,
|
||||
|
||||
/// Index mode: auto (default), off (no index), rebuild (force rebuild)
|
||||
#[arg(long, value_enum, default_value_t = IndexMode::Auto)]
|
||||
#[arg(long, value_enum, default_value_t = IndexMode::Auto, help_heading = "Analysis")]
|
||||
index: IndexMode,
|
||||
|
||||
/// Output format (defaults to config's default_format, or "console")
|
||||
#[arg(short, long, value_enum)]
|
||||
#[arg(short, long, value_enum, help_heading = "Output")]
|
||||
format: Option<OutputFormat>,
|
||||
|
||||
/// Severity filter expression: HIGH, HIGH,MEDIUM, or >=MEDIUM
|
||||
|
|
@ -179,30 +195,30 @@ pub enum Commands {
|
|||
/// Filters findings AFTER all severity normalization (e.g. nonprod
|
||||
/// downgrades). Only findings matching the expression are emitted.
|
||||
/// Case-insensitive. Shell-quote expressions containing ">".
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
severity: Option<String>,
|
||||
|
||||
/// Analysis mode: full (default), ast, cfg, taint
|
||||
#[arg(long, value_enum, default_value_t = ScanMode::Full)]
|
||||
#[arg(long, value_enum, default_value_t = ScanMode::Full, help_heading = "Analysis")]
|
||||
mode: ScanMode,
|
||||
|
||||
/// Named scan profile to apply (e.g. quick, full, ci, taint_only, conservative_large_repo)
|
||||
///
|
||||
/// Profiles override scan-related config settings. CLI flags still
|
||||
/// take precedence over profile values.
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Analysis")]
|
||||
profile: Option<String>,
|
||||
|
||||
/// Engine-depth shortcut: fast, balanced, or deep. Sets the full
|
||||
/// stack of analysis toggles at once; individual engine flags still
|
||||
/// override this after application.
|
||||
#[arg(long, value_enum)]
|
||||
#[arg(long, value_enum, help_heading = "Analysis")]
|
||||
engine_profile: Option<EngineProfile>,
|
||||
|
||||
/// Print the effective engine configuration and exit without
|
||||
/// scanning. Useful for understanding how CLI flags and config
|
||||
/// values resolve together.
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Analysis")]
|
||||
explain_engine: bool,
|
||||
|
||||
/// Scan all targets (alias for --mode full)
|
||||
|
|
@ -213,57 +229,57 @@ pub enum Commands {
|
|||
///
|
||||
/// By default, findings in non-production paths are downgraded by one
|
||||
/// severity tier. This flag preserves original severity.
|
||||
#[arg(long, alias = "include-nonprod")]
|
||||
#[arg(long, alias = "include-nonprod", help_heading = "Output")]
|
||||
keep_nonprod_severity: bool,
|
||||
|
||||
/// Suppress all human-readable status output
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
quiet: bool,
|
||||
|
||||
/// Exit with code 1 if any finding meets or exceeds this severity
|
||||
///
|
||||
/// Useful for CI gating. Example: --fail-on HIGH
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
fail_on: Option<String>,
|
||||
|
||||
/// Disable state-model analysis (resource lifecycle, auth state)
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Analysis")]
|
||||
no_state: bool,
|
||||
|
||||
/// Disable attack-surface ranking (findings are sorted by exploitability by default)
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
no_rank: bool,
|
||||
|
||||
/// Show inline-suppressed findings (dimmed, tagged [SUPPRESSED])
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
show_suppressed: bool,
|
||||
|
||||
/// Show all findings: disables category filtering, rollups, and LOW budgets
|
||||
#[arg(long = "all")]
|
||||
#[arg(long = "all", help_heading = "Output")]
|
||||
show_all: bool,
|
||||
|
||||
/// Include Quality findings (excluded by default)
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
include_quality: bool,
|
||||
|
||||
/// Maximum total LOW findings to show
|
||||
#[arg(long, default_value_t = 20)]
|
||||
#[arg(long, default_value_t = 20, help_heading = "Output")]
|
||||
max_low: u32,
|
||||
|
||||
/// Maximum LOW findings per file
|
||||
#[arg(long, default_value_t = 1)]
|
||||
#[arg(long, default_value_t = 1, help_heading = "Output")]
|
||||
max_low_per_file: u32,
|
||||
|
||||
/// Maximum LOW findings per rule
|
||||
#[arg(long, default_value_t = 10)]
|
||||
#[arg(long, default_value_t = 10, help_heading = "Output")]
|
||||
max_low_per_rule: u32,
|
||||
|
||||
/// Number of example locations in rollup findings
|
||||
#[arg(long, default_value_t = 5)]
|
||||
#[arg(long, default_value_t = 5, help_heading = "Output")]
|
||||
rollup_examples: u32,
|
||||
|
||||
/// Show all instances for a specific rule (bypasses rollup for that rule)
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
show_instances: Option<String>,
|
||||
|
||||
/// Minimum attack-surface score to include in output
|
||||
|
|
@ -271,89 +287,97 @@ pub enum Commands {
|
|||
/// Findings with a rank score below this threshold are suppressed.
|
||||
/// Requires ranking to be enabled (has no effect with --no-rank).
|
||||
/// Example: --min-score 50
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
min_score: Option<u32>,
|
||||
|
||||
/// Minimum confidence level to include in output
|
||||
///
|
||||
/// Values: low, medium, high. Findings below this level are dropped.
|
||||
/// JSON/SARIF include all unless filtered.
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
min_confidence: Option<String>,
|
||||
|
||||
/// Drop findings emitted from capped / widened / bailed analysis
|
||||
///
|
||||
/// Suppresses any finding whose engine provenance notes indicate
|
||||
/// over-reporting (predicate/path widening) or analysis bail
|
||||
/// (SSA lowering failure, parse timeout). Under-report notes —
|
||||
/// where the emitted finding is still a real flow but the
|
||||
/// result set is a lower bound — are kept.
|
||||
/// (SSA lowering failure, parse timeout). Under-report notes
|
||||
/// (where the emitted finding is still a real flow but the
|
||||
/// result set is a lower bound) are kept.
|
||||
///
|
||||
/// Intended for strict CI gates where a finding from non-converged
|
||||
/// analysis is worse than no finding. Applied after ranking and
|
||||
/// before the `max_results` truncation.
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Output")]
|
||||
require_converged: bool,
|
||||
|
||||
// ── Analysis engine toggles (override [analysis.engine] config) ───
|
||||
/// Enable path-constraint solving (default: on)
|
||||
#[arg(long, overrides_with = "no_constraint_solving")]
|
||||
#[arg(
|
||||
long,
|
||||
overrides_with = "no_constraint_solving",
|
||||
help_heading = "Engine"
|
||||
)]
|
||||
constraint_solving: bool,
|
||||
/// Disable path-constraint solving
|
||||
#[arg(long, overrides_with = "constraint_solving")]
|
||||
#[arg(long, overrides_with = "constraint_solving", help_heading = "Engine")]
|
||||
no_constraint_solving: bool,
|
||||
|
||||
/// Enable abstract interpretation (default: on)
|
||||
#[arg(long, overrides_with = "no_abstract_interp")]
|
||||
#[arg(long, overrides_with = "no_abstract_interp", help_heading = "Engine")]
|
||||
abstract_interp: bool,
|
||||
/// Disable abstract interpretation
|
||||
#[arg(long, overrides_with = "abstract_interp")]
|
||||
#[arg(long, overrides_with = "abstract_interp", help_heading = "Engine")]
|
||||
no_abstract_interp: bool,
|
||||
|
||||
/// Enable k=1 context-sensitive callee inlining (default: on)
|
||||
#[arg(long, overrides_with = "no_context_sensitive")]
|
||||
#[arg(long, overrides_with = "no_context_sensitive", help_heading = "Engine")]
|
||||
context_sensitive: bool,
|
||||
/// Disable context-sensitive callee inlining
|
||||
#[arg(long, overrides_with = "context_sensitive")]
|
||||
#[arg(long, overrides_with = "context_sensitive", help_heading = "Engine")]
|
||||
no_context_sensitive: bool,
|
||||
|
||||
/// Enable the symex pipeline (default: on)
|
||||
#[arg(long, overrides_with = "no_symex")]
|
||||
#[arg(long, overrides_with = "no_symex", help_heading = "Symex")]
|
||||
symex: bool,
|
||||
/// Disable the symex pipeline entirely
|
||||
#[arg(long, overrides_with = "symex")]
|
||||
#[arg(long, overrides_with = "symex", help_heading = "Symex")]
|
||||
no_symex: bool,
|
||||
|
||||
/// Enable cross-file symbolic body execution (default: on)
|
||||
#[arg(long, overrides_with = "no_cross_file_symex")]
|
||||
#[arg(long, overrides_with = "no_cross_file_symex", help_heading = "Symex")]
|
||||
cross_file_symex: bool,
|
||||
/// Disable cross-file symbolic body execution
|
||||
#[arg(long, overrides_with = "cross_file_symex")]
|
||||
#[arg(long, overrides_with = "cross_file_symex", help_heading = "Symex")]
|
||||
no_cross_file_symex: bool,
|
||||
|
||||
/// Enable interprocedural symex frame stack (default: on)
|
||||
#[arg(long, overrides_with = "no_symex_interproc")]
|
||||
#[arg(long, overrides_with = "no_symex_interproc", help_heading = "Symex")]
|
||||
symex_interproc: bool,
|
||||
/// Disable interprocedural symex
|
||||
#[arg(long, overrides_with = "symex_interproc")]
|
||||
#[arg(long, overrides_with = "symex_interproc", help_heading = "Symex")]
|
||||
no_symex_interproc: bool,
|
||||
|
||||
/// Enable SMT solver backend when nyx is built with the `smt` feature (default: on)
|
||||
#[arg(long, overrides_with = "no_smt")]
|
||||
#[arg(long, overrides_with = "no_smt", help_heading = "Symex")]
|
||||
smt: bool,
|
||||
/// Disable SMT solver backend
|
||||
#[arg(long, overrides_with = "smt")]
|
||||
#[arg(long, overrides_with = "smt", help_heading = "Symex")]
|
||||
no_smt: bool,
|
||||
|
||||
/// Enable demand-driven backwards analysis (default: off)
|
||||
#[arg(long, overrides_with = "no_backwards_analysis")]
|
||||
#[arg(
|
||||
long,
|
||||
overrides_with = "no_backwards_analysis",
|
||||
help_heading = "Engine"
|
||||
)]
|
||||
backwards_analysis: bool,
|
||||
/// Disable demand-driven backwards analysis
|
||||
#[arg(long, overrides_with = "backwards_analysis")]
|
||||
#[arg(long, overrides_with = "backwards_analysis", help_heading = "Engine")]
|
||||
no_backwards_analysis: bool,
|
||||
|
||||
/// Override per-file tree-sitter parse timeout (ms). 0 disables the cap.
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Limits")]
|
||||
parse_timeout_ms: Option<u64>,
|
||||
|
||||
/// Maximum taint origins retained per lattice value (default: 32).
|
||||
|
|
@ -363,7 +387,7 @@ pub enum Commands {
|
|||
/// `OriginsTruncated` engine note is recorded on affected findings.
|
||||
/// Raise for very wide codebases where truncation is observed;
|
||||
/// lower only when lattice width is a measured bottleneck.
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Limits")]
|
||||
max_origins: Option<u32>,
|
||||
|
||||
/// Maximum abstract heap objects retained per points-to set (default: 32).
|
||||
|
|
@ -373,7 +397,7 @@ pub enum Commands {
|
|||
/// `PointsToTruncated` engine note is recorded on affected findings.
|
||||
/// Raise for factory-heavy codebases where truncation is observed;
|
||||
/// lower only when points-to width is a measured bottleneck.
|
||||
#[arg(long)]
|
||||
#[arg(long, help_heading = "Limits")]
|
||||
max_pointsto: Option<u32>,
|
||||
|
||||
// ── Deprecated aliases (hidden) ─────────────────────────────────
|
||||
|
|
@ -449,8 +473,15 @@ pub enum Commands {
|
|||
|
||||
#[derive(Subcommand)]
|
||||
pub enum ConfigAction {
|
||||
/// Print effective merged configuration as TOML
|
||||
Show,
|
||||
/// Print configuration as TOML. By default shows only the values
|
||||
/// that differ from built-in defaults. Pass `--all` for the full
|
||||
/// effective configuration.
|
||||
Show {
|
||||
/// Print the full effective configuration instead of just
|
||||
/// the user's overrides.
|
||||
#[arg(long)]
|
||||
all: bool,
|
||||
},
|
||||
|
||||
/// Print configuration directory path
|
||||
Path,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue