nyx-scanner 0.6.1

A multi-language static analysis tool for detecting security vulnerabilities
Documentation
use crate::evidence::Confidence;
use crate::patterns::{Pattern, PatternCategory, PatternTier, Severity};

/// C AST patterns.
///
/// Taint rules cover `system`/`popen`/`exec*` (command injection),
/// `sprintf`/`strcpy`/`strcat` (buffer overflow sinks), and `printf`/`fprintf`
/// (format-string sinks).  AST patterns here focus on **banned-by-default
/// functions** (`gets`, `scanf %s`) and **format-string** variants not covered
/// by taint, since these are dangerous regardless of data origin.
pub const PATTERNS: &[Pattern] = &[
    // ── Tier A: Banned functions (always dangerous) ────────────────────
    Pattern {
        id: "c.memory.gets",
        description: "gets() has no bounds checking and is always exploitable",
        query: r#"(call_expression function: (identifier) @id (#eq? @id "gets")) @vuln"#,
        severity: Severity::High,
        tier: PatternTier::A,
        category: PatternCategory::MemorySafety,
        confidence: Confidence::High,
    },
    Pattern {
        id: "c.memory.strcpy",
        description: "strcpy() does not bounds-check the destination buffer",
        query: r#"(call_expression function: (identifier) @id (#eq? @id "strcpy")) @vuln"#,
        severity: Severity::High,
        tier: PatternTier::A,
        category: PatternCategory::MemorySafety,
        confidence: Confidence::High,
    },
    Pattern {
        id: "c.memory.strcat",
        description: "strcat() does not bounds-check the destination buffer",
        query: r#"(call_expression function: (identifier) @id (#eq? @id "strcat")) @vuln"#,
        severity: Severity::High,
        tier: PatternTier::A,
        category: PatternCategory::MemorySafety,
        confidence: Confidence::High,
    },
    Pattern {
        id: "c.memory.sprintf",
        description: "sprintf() does not limit the output buffer length",
        query: r#"(call_expression function: (identifier) @id (#eq? @id "sprintf")) @vuln"#,
        severity: Severity::High,
        tier: PatternTier::A,
        category: PatternCategory::MemorySafety,
        confidence: Confidence::High,
    },
    Pattern {
        id: "c.memory.scanf_percent_s",
        description: "scanf(\"%s\") performs an unbounded string read",
        query: r#"(call_expression
                     function: (identifier) @id (#eq? @id "scanf")
                     arguments: (argument_list
                       (string_literal) @fmt (#match? @fmt "%s")))
                   @vuln"#,
        severity: Severity::High,
        tier: PatternTier::A,
        category: PatternCategory::MemorySafety,
        confidence: Confidence::High,
    },
    // ── Tier A: Command execution ──────────────────────────────────────
    Pattern {
        id: "c.cmdi.system",
        description: "system() runs a shell command",
        query: r#"(call_expression function: (identifier) @id (#eq? @id "system")) @vuln"#,
        severity: Severity::High,
        tier: PatternTier::A,
        category: PatternCategory::CommandExec,
        confidence: Confidence::High,
    },
    Pattern {
        id: "c.cmdi.popen",
        description: "popen() runs a shell command and returns a pipe",
        query: r#"(call_expression function: (identifier) @id (#eq? @id "popen")) @vuln"#,
        severity: Severity::Medium,
        tier: PatternTier::A,
        category: PatternCategory::CommandExec,
        confidence: Confidence::High,
    },
    // ── Tier A: Format-string ──────────────────────────────────────────
    Pattern {
        id: "c.memory.printf_no_fmt",
        description: "printf(var) is a format-string vulnerability when the first arg is not a literal",
        query: r#"(call_expression
                     function: (identifier) @id (#eq? @id "printf")
                     arguments: (argument_list
                       . (identifier) @arg))
                   @vuln"#,
        severity: Severity::High,
        tier: PatternTier::B,
        category: PatternCategory::MemorySafety,
        confidence: Confidence::Medium,
    },
];