Security Scanning

Two-track security scanning policy (spec: docs/superpowers/specs/2026-04-16-security-scan-severity-policy-design.md): the PR gate blocks only HIGH/CRITICAL, while a daily scheduled scan tracks everything MEDIUM+ as GitHub issues.

Two-Track Policy

ToolPR-gate (blocks merge)Scheduled scan (daily 02:00 UTC, *-latest images)
TrivyHIGH/CRITICALMEDIUM+ → tracking issue + auto-ignore PR
npm auditHIGH/CRITICAL (with ignore list)MODERATE+ → tracking issue
bun auditHIGH/CRITICALMODERATE+ → tracking issue
Semgreperror level (HIGH/CRITICAL)error + warning → tracking issue + auto-ignore PR
GitleaksAll findingsAll findings

MODERATE/MEDIUM findings never block a PR — they surface as tracking issues with an SLA instead.

Workflows

WorkflowTriggerPurpose
.github/workflows/security-scan.ymlworkflow_call from pr-preview.yml + daily 02:00 UTCPR-gate scans (all 5 tools)
.github/workflows/security-scan-scheduled.ymlDaily 02:00 UTC + Mondays 08:00 UTCScheduled MEDIUM+ scan of *-latest images; Monday cron posts the weekly Teams digest
.github/workflows/container-security-scan.ymlworkflow_call on image buildTrivy container-specific scan

Results report to the GitHub Security Tab (Code Scanning) and as PR comments.

Reconciliation (scripts/security-scan-reconcile/)

TypeScript tooling that turns scheduled-scan findings into process:

  • reconcile.ts — creates/updates one tracking issue per finding, opens auto-ignore PRs for accepted findings
  • pr-gate-filter.ts — severity-aware filter so the PR gate honours the ignore list (HIGH/CRITICAL only)
  • digest.ts — weekly Teams digest of open findings
  • SLA: MEDIUM findings get GitHub issues, labelled security:overdue at 60 days

Renovate handles vulnerability-driven dependency bumps (vulnerabilityAlerts in renovate.json5).

False Positive Management

ToolConfig FilePurpose
Semgrep.semgrepignore (repo root)Exclude paths/rules
Trivy.trivyignore (repo root + renewa-one/.trivyignore)Ignore specific CVEs
Gitleaks.gitleaks.toml (repo root)Exclude known safe patterns

CVE ignore example — when a vulnerability has no available fix:

# .trivyignore
CVE-2026-32280  # Atlas Go stdlib x509 DoS - no upstream fix

Key Principles

  • PR-gate scans feed the ci-gate required check (see CI-CD Workflows) — only HIGH/CRITICAL block
  • Scheduled daily scans catch newly disclosed CVEs in already-shipped images
  • Coding Guidelines enforce secure coding patterns (XSS protection, input sanitization)
  • App secrets live in Infisical EU, not GitHub environment secrets (fixed PR#1930); GitHub secrets are CI-infra credentials only

Key Files

  • .github/workflows/security-scan.yml
  • .github/workflows/security-scan-scheduled.yml
  • .github/workflows/container-security-scan.yml
  • scripts/security-scan-reconcile/
  • .trivyignore, .semgrepignore, .gitleaks.toml
  • docs/superpowers/specs/2026-04-16-security-scan-severity-policy-design.md

See Also