vsec 0.0.1

Detect secrets and in Rust codebases
Documentation
// src/models/comparison.rs

/// Represents an equality comparison in code
#[derive(Debug, Clone)]
pub struct Comparison {
    /// The left side of the comparison
    pub left: ComparisonSide,

    /// The right side of the comparison
    pub right: ComparisonSide,

    /// The comparison operator
    pub operator: ComparisonOp,

    /// The consequence (what happens if comparison succeeds)
    pub consequence: Option<Consequence>,

    /// Whether left and right are swapped from canonical form
    /// (canonical: variable == constant)
    pub is_swapped: bool,
}

impl Comparison {
    /// Get the constant side (if any)
    pub fn constant_side(&self) -> Option<&ComparisonSide> {
        if self.left.is_constant() {
            Some(&self.left)
        } else if self.right.is_constant() {
            Some(&self.right)
        } else {
            None
        }
    }

    /// Get the variable side (if any)
    pub fn variable_side(&self) -> Option<&ComparisonSide> {
        if self.left.is_variable() {
            Some(&self.left)
        } else if self.right.is_variable() {
            Some(&self.right)
        } else {
            None
        }
    }
}

/// One side of a comparison
#[derive(Debug, Clone)]
pub enum ComparisonSide {
    /// A constant reference: `SECRET_KEY`
    ConstantRef {
        name: String,
        resolved_value: Option<String>,
    },

    /// A string literal: `"secret"`
    StringLiteral(String),

    /// A variable: `input`
    Variable {
        name: String,
        source: Option<VariableSource>,
    },

    /// A field access: `request.header`
    FieldAccess { base: String, field: String },

    /// A method call: `headers.get("auth")`
    MethodCall {
        receiver: String,
        method: String,
        args: Vec<String>,
    },

    /// A function call: `env::var("TOKEN")`
    FunctionCall { path: String, args: Vec<String> },

    /// Something else
    Other(String),
}

impl ComparisonSide {
    pub fn is_constant(&self) -> bool {
        matches!(self, Self::ConstantRef { .. } | Self::StringLiteral(_))
    }

    pub fn is_variable(&self) -> bool {
        matches!(self, Self::Variable { .. } | Self::FieldAccess { .. })
    }

    /// Get the name for scoring (variable name, field name, etc.)
    pub fn name_for_scoring(&self) -> Option<&str> {
        match self {
            Self::Variable { name, .. } => Some(name),
            Self::FieldAccess { field, .. } => Some(field),
            Self::MethodCall { method, .. } => Some(method),
            _ => None,
        }
    }
}

/// Where a variable came from
#[derive(Debug, Clone)]
pub enum VariableSource {
    /// Function parameter
    Parameter,

    /// Environment variable
    Environment,

    /// HTTP header
    Header,

    /// HTTP query parameter
    QueryParam,

    /// HTTP body
    RequestBody,

    /// File contents
    FileRead,

    /// User input
    Stdin,

    /// Database query
    Database,

    /// Unknown
    Unknown,
}

/// Comparison operators
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComparisonOp {
    /// `==`
    Eq,
    /// `!=`
    Ne,
    /// `.eq()`
    MethodEq,
    /// `matches!`
    PatternMatch,
}

/// What happens after the comparison
#[derive(Debug, Clone)]
pub struct Consequence {
    /// The block of code that executes
    pub block_summary: BlockSummary,

    /// Specific dangerous operations found
    pub dangerous_ops: Vec<DangerousOp>,

    /// Whether this seems benign
    pub is_benign: bool,
}

/// Summary of a code block's effects
#[derive(Debug, Clone, Default)]
pub struct BlockSummary {
    /// Is the block empty?
    pub is_empty: bool,

    /// Only contains logging/printing?
    pub only_logging: bool,

    /// Contains return statement?
    pub has_return: bool,

    /// Contains early exit (return, break, continue)?
    pub has_early_exit: bool,

    /// Contains state mutation?
    pub has_mutation: bool,

    /// Contains function calls?
    pub function_calls: Vec<String>,

    /// Contains field assignments?
    pub field_assignments: Vec<String>,
}

/// Dangerous operations that raise score
#[derive(Debug, Clone)]
pub enum DangerousOp {
    /// Setting admin/auth state
    AuthStateChange { field: String },

    /// Calling auth-related function
    AuthFunctionCall { function: String },

    /// Process control (exit, exec, spawn)
    ProcessControl { function: String },

    /// Database operation
    DatabaseOp { operation: String },

    /// Network operation
    NetworkOp { operation: String },

    /// File system operation
    FileSystemOp { operation: String },

    /// Cryptographic operation
    CryptoOp { operation: String },
}