Skip to content

feat: unified security scanner — integrate semgrep as primary SAST backend #228

Description

@rocklambros

Problem

zerg.security.scanner (scanner.py, 679 lines) is 100% regex-based. It matches text patterns from PATTERN_REGISTRY (patterns.py, 1017 lines) but has no AST awareness, no taint tracking, and high false positive rates (matches patterns in comments, strings, docstrings). It cannot detect context-dependent vulnerabilities like SQL injection via variable flow or auth bypass through logic errors.

Meanwhile, semgrep provides AST-aware analysis, taint tracking (Pro), 30+ language support, and ships a p/bandit ruleset that covers ~95% of bandit's Python checks — making a separate bandit install redundant.

Proposed Solution

Integrate semgrep into run_security_scan() as an additional scan backend alongside existing regex patterns and CVE scanning. The scanner becomes an orchestrator:

run_security_scan(files)
  → 1. Semgrep scan (AST-aware, p/security-audit + p/bandit rulesets)
  → 2. Regex pattern scan (PATTERN_REGISTRY — catches custom patterns semgrep doesn't cover)
  → 3. CVE dependency scan (osv.dev API via cve.py)
  → Merge all findings into unified SecurityResult

Key Design Decisions

  • Semgrep is the primary SAST tool — no bandit (semgrep's p/bandit covers it)
  • Regex patterns retained as supplementary — they catch ZERG-specific patterns and custom secret formats
  • Graceful degradation — if semgrep not installed, scanner falls back to regex-only with a warning
  • SARIF output — semgrep natively outputs SARIF, enabling GitHub Security tab integration

Files to Modify

File Change
zerg/security/scanner.py Add _run_semgrep() backend, integrate into run_security_scan()
zerg/security/__init__.py Export new scan backends
zerg/security/patterns.py Add semgrep_rule_id field to SecurityPattern for dedup with semgrep findings
tests/unit/test_security_engine.py Test semgrep integration, fallback behavior
tests/integration/test_security_scan.py End-to-end scan with semgrep installed

Acceptance Criteria

  • run_security_scan() calls semgrep when available
  • Semgrep findings merged into SecurityResult with CWE mappings
  • Graceful fallback to regex-only when semgrep not installed
  • No duplicate findings when semgrep and regex detect the same issue
  • SARIF output generation from scan results
  • Rulesets configurable via .zerg/config.yaml

Depends On

  • None (foundational)

Blocks

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High priorityenhancementNew feature or requestsecuritySecurity vulnerabilities and hardening

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions