Vsec
A research-grade static analysis tool for detecting hardcoded secrets in Rust codebases with intelligent false-positive filtering.
Features
- Two-Pass Architecture: Indexes constants across files, then analyzes usage patterns
- Four-Layer Filter Pipeline: Dramatically reduces false positives through:
- Layer 1: Name analysis (benign vs suspicious terms)
- Layer 2: Scope isolation (test/example/benchmark detection)
- Layer 3: Consequence analysis (what happens if comparison succeeds)
- Layer 4: RHS analysis (command routing vs authentication)
- Score-Based Detection: 0-100+ scoring with configurable thresholds
- Multiple Output Formats: Text, JSON, SARIF, Markdown, GitHub Actions
- Parallel Processing: Uses rayon for fast scanning of large codebases
- Configurable Sensitivity: From paranoid (catch everything) to minimal (high confidence only)
- Git History Scanning: Find deleted secrets in commit history with
--scan-history
Installation
Or build from source:
Usage
Scan a Directory
# Scan directory
# Scan with lower threshold (more findings)
# Include test and example files
# Output as JSON
# Output as SARIF (for CI integration)
# Fail CI if findings exist
Initialize Configuration
# Create default config file
# Create minimal config
# Specify output path
Explain a Finding
# Get details about a specific finding
Debug Mode
# Show parsing details for a file
# Include AST dump
Git History Scanning
Scan git history to find secrets that were committed and later deleted:
# Scan git history (requires --scan-history flag)
# Limit to last 100 commits
# Only scan commits after a specific date
# Combine with other options
Note: Git history scanning is opt-in because it can be slow on large repositories with many commits. Use it for security audits, not daily CI.
Configuration
Create a .vsec.toml file in your project root:
[]
# Sensitivity preset: "paranoid", "high", "normal", "low", or a number
= "normal"
[]
# Patterns to ignore
= ["target", "vendor", ".git"]
# Include test files in scan
= false
# Include example files in scan
= false
[]
# Show score breakdown for each finding
= false
# Show remediation suggestions
= true
Sensitivity Presets
| Preset | Threshold | Use Case |
|---|---|---|
paranoid |
40 | Security audits, pre-release reviews |
high |
55 | CI/CD with manual review |
normal |
70 | Regular development (default) |
low |
85 | Large codebases, automated blocking |
How It Works
Detection Strategy
Secretrace focuses on equality comparisons involving string constants, not just constant definitions. This approach catches actual authentication bypass vulnerabilities:
// This pattern is detected:
const AUTH_TOKEN: &str = "sk_live_12345";
False Positive Filtering
The four-layer filter pipeline eliminates common false positives:
- Name Analysis:
VERSION,COLOR,HELP_TEXTare benign - Scope Isolation: Test files, examples, and benchmarks are filtered
- Consequence Analysis: Logging-only blocks are deprioritized
- RHS Analysis: Command routing (
if cmd == "help") is filtered
Scoring Factors
Findings are scored based on multiple factors:
| Factor | Impact |
|---|---|
| Suspicious name (password, secret, key) | +20 to +40 |
| High entropy value | +20 |
| Auth consequence (grant_access, authorize) | +25 |
| Long value (32+ chars) | +15 |
| Benign name (version, color, help) | -100 (killed) |
| Test context | -100 (killed) |
| Short value (<8 chars) | -20 |
| Placeholder pattern | -50 |
Output Formats
Text (default)
Human-readable output with colors and formatting.
JSON
Machine-readable format for tooling integration.
SARIF
Static Analysis Results Interchange Format for CI/CD integration (GitHub, Azure DevOps, etc.)
Markdown
Report format suitable for documentation or PR comments.
GitHub
GitHub Actions annotation format for inline PR comments.
CI Integration
GitHub Actions
- name: Scan for secrets
run: |
cargo install vsec
vsec scan -f sarif -o results.sarif --fail-on-findings
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: results.sarif
Pre-commit Hook
#!/bin/bash
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Scanner │
├─────────────────────────────────────────────────────────────┤
│ Phase 1: Indexer │
│ - Parallel file parsing (rayon + syn) │
│ - Build SuspectRegistry (DashMap) │
│ - Index public constants │
├─────────────────────────────────────────────────────────────┤
│ Phase 2: Analyzer │
│ - Find equality comparisons │
│ - Resolve constant references │
│ - Run filter pipeline │
│ - Score findings │
├─────────────────────────────────────────────────────────────┤
│ Filter Pipeline │
│ ┌─────────┐ ┌─────────┐ ┌─────────────┐ ┌────────────┐ │
│ │ Layer 1 │→│ Layer 2 │→│ Layer 3 │→│ Layer 4 │ │
│ │ Names │ │ Scope │ │ Consequence │ │ RHS │ │
│ └─────────┘ └─────────┘ └─────────────┘ └────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Scoring Engine │
│ - Entropy analysis │
│ - Pattern matching │
│ - Factor aggregation │
│ - Threshold application │
└─────────────────────────────────────────────────────────────┘
License
Vsec is dual-licensed under either:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
at your option.