Scan product guide

Core + opt-in scanners, SARIF, policies, and CI examples

Scan any repository for vulnerabilities with one Docker image. No account, database, or platform required.

deps-cves (OSV/GHSA dependency CVEs) + Trivy (dependencies/images/config) + Semgrep (code/SAST) + Syft (SBOM) + Gitleaks (secrets) + Checkov (IaC), optional segrep-sast (native Tree-sitter SAST), optional segrep-sbom (local lockfile SBOM + parity shadow), optional segrep-vuln (local lockfile vulnerability scanning + Trivy parity shadow), optional segrep-dast (broader local passive runtime checks + ZAP parity shadow), optional segrep-license (license compliance with SPDX risk classification), optional segrep-secrets (native regex-based secret detection), optional segrep-iac (local IaC misconfiguration scanner), optional segrep-cloud (cloud credential and IAM misconfiguration scanner), optional AI remediation summary, CI-friendly JSON output.

Quick start

Pull the image

After a release is published:

docker pull ghcr.io/szaranger/security-scanner:latest

Until then, build from source:

git clone https://github.com/szaranger/security.git
cd security
pnpm docker:build
# image tag: security-scanner:local

Set IMAGE=ghcr.io/szaranger/security-scanner:latest or IMAGE=security-scanner:local below.

Scan the current directory

docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo

Scan with CI exit code (fail on high+)

docker run --rm -v "$(pwd):/repo:ro" $IMAGE \
  scan /repo --format json --fail-on high

Exit code 1 when findings meet the threshold; 0 otherwise.


What you get

ScannerFinds
deps-cvesDependency CVEs from OSV with GHSA/CVE alias mapping for npm lockfile packages
TrivyDependency CVEs, misconfigurations in manifests/lockfiles
SemgrepCode patterns, insecure APIs, SAST-style issues
SyftSoftware bill of materials (CycloneDX JSON artifact)
GitleaksHardcoded secrets, API keys, tokens
CheckovTerraform, Kubernetes, Dockerfile, and other IaC misconfigurations
segrep-sast (opt-in)Native SAST — Tree-sitter AST rules, dataflow/taint, AI per-finding enrichment
segrep-sbom (opt-in)Local lockfile SBOM generator with optional external Syft parity shadow report
segrep-vuln (opt-in)Local lockfile vulnerability scanner with optional external Trivy parity shadow report
segrep-dast (opt-in)Local passive DAST scanner for broader deterministic runtime checks with optional external ZAP parity shadow
segrep-license (opt-in)License compliance scanner — classifies dependency licenses by risk tier and flags copyleft or unknown licenses
segrep-secrets (opt-in)Native secret scanner — regex-based detection of API keys, tokens, passwords, private keys, and connection strings
segrep-iac (opt-in)Local IaC misconfiguration scanner — Terraform, Kubernetes manifest, and Dockerfile checks
segrep-cloud (opt-in)Cloud security scanner — AWS/GCP/Azure credentials, IAM policies, Terraform, CloudFormation, Serverless, Docker, and Kubernetes cloud misconfigurations

Opt-in: segrep-sast, segrep-sbom, segrep-vuln, segrep-dast, segrep-license, segrep-secrets, segrep-iac, and segrep-cloud are not included in --scanners all.

Output formats:

  • terminal (default) — human-readable summary + optional AI remediation
  • json — structured results for CI dashboards or parsers

CLI flags

scan [path] [--format terminal|json|sarif] [--scanners deps-cves,trivy,semgrep,syft,gitleaks,checkov,zap,kubescape,prowler,segrep-sast,segrep-sbom,segrep-vuln,segrep-dast,segrep-license,segrep-secrets,segrep-iac,segrep-cloud|all] [--target-url URL] [--kubeconfig path] [--aws-profile name] [--changed-only] [--base-ref main] [--fail-on critical|high|medium|low|none]
FlagDefaultDescription
path.Directory inside the container (usually /repo)
--formatterminalterminal, json, or sarif
--scannersall registered scannersComma-separated list or all
--changed-onlyoffLimit findings to files changed vs --base-ref
--base-refmainBase git ref for --changed-only
--fail-onnoneExit 1 if findings at or above this severity (overridden by .segrep/policy.yml)
--target-urlRequired for ZAP and segrep-dast. DAST target URL (opt-in; authorized targets only)
--kubeconfigKubeconfig path for Kubescape cluster scans
--aws-profileAWS profile for Prowler (credentials never persisted)

Opt-in scanners: zap (DAST), kubescape (Kubernetes), prowler (AWS), segrep-sast (native SAST), segrep-sbom (local SBOM), segrep-vuln (local dependency vuln scanner), segrep-dast (local passive DAST), segrep-license (license compliance), segrep-secrets (native secret detection), segrep-iac (local IaC misconfig scanner), segrep-cloud (cloud credential and IAM scanner). They are registered but excluded from --scanners all (which runs the six core repo scanners). Select them explicitly when needed.

# Native SAST only
scan /repo --scanners segrep-sast

# Semgrep + native SAST
scan /repo --scanners semgrep,segrep-sast

# Local lockfile SBOM
scan /repo --scanners segrep-sbom

# Local lockfile vulnerabilities
scan /repo --scanners segrep-vuln

# Local passive DAST checks
scan /repo --scanners segrep-dast --target-url http://127.0.0.1:4010

See segrep-sast.md for engine config (segrep.yaml), custom rules, and dataflow analysis. See segrep-sbom.md for segrep-sbom modes, parity shadow output, and CI drift gates. See segrep-vuln.md for segrep-vuln modes, parity shadow output, and CI drift gates. See segrep-dast.md for segrep-dast local passive checks and --target-url usage. See segrep-license.md for segrep-license SPDX classification and policy integration. See segrep-secrets.md for segrep-secrets regex rules, file coverage, and relationship to gitleaks. See segrep-iac.md for segrep-iac Terraform, Kubernetes, and Dockerfile checks. See segrep-cloud.md for segrep-cloud cloud credential, IAM, and cloud resource checks.

segrep-sbom environment variables:

  • SEGREP_SBOM_MODE=auto|local|external (default auto)
  • SEGREP_SBOM_PARITY_SHADOW=true to compare local output against external Syft and write .segrep/segrep-sbom-parity.json

segrep-vuln environment variables:

  • SEGREP_VULN_MODE=auto|local|external (default auto)
  • SEGREP_VULN_PARITY_SHADOW=true to compare local findings against external Trivy and write .segrep/segrep-vuln-parity.json

segrep-vuln local mode supports package-lock.json, pnpm-lock.yaml, yarn.lock, requirements.txt, and poetry.lock.

segrep-dast environment variables:

  • SEGREP_DAST_MODE=auto|local|external (default auto)
  • SEGREP_DAST_PARITY_SHADOW=true to compare local findings against external ZAP and write .segrep/segrep-dast-parity.json
  • SEGREP_DAST_TIMEOUT_MS for request timeout
  • SEGREP_DAST_USER_AGENT to override the default user agent
  • SEGREP_DAST_DISCLOSURE_PATHS for comma-separated disclosure probes

Environment variables: ZAP_BASELINE_TIMEOUT (default 300), KUBESCAPE_FRAMEWORK (default nsa), AWS_PROFILE.

Examples

Trivy only:

docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners trivy

JSON to a file:

docker run --rm -v "$(pwd):/repo:ro" $IMAGE \
  scan /repo --format json > scan-results.json

All scanners:

docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners all

SBOM only (writes .segrep/sbom.cyclonedx.json inside the scan target — use a read-write mount if you need the file on disk):

docker run --rm -v "$(pwd):/repo" $IMAGE scan /repo --scanners syft --format json

# Local SBOM with parity shadow report
docker run --rm -v "$(pwd):/repo" -e SEGREP_SBOM_PARITY_SHADOW=true $IMAGE scan /repo --scanners segrep-sbom --format json

DAST (requires Docker for ZAP fallback; authorized URLs only):

docker run --rm --network host $IMAGE scan /repo --scanners zap --target-url https://staging.example.com

# Local passive DAST checks
docker run --rm --network host $IMAGE scan /repo --scanners segrep-dast --target-url https://staging.example.com

License compliance:

docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners segrep-license

# Fail CI on strong copyleft licenses
docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners segrep-license --fail-on high

Kubernetes manifests (no cluster required):

docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo/k8s --scanners kubescape

AWS posture (read-only credentials via env):

docker run --rm -e AWS_PROFILE=readonly -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners prowler

Cloud credential and IAM scanning (no AWS credentials needed):

docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners segrep-cloud

# Combine with IaC scanning
docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners segrep-cloud,segrep-iac

AI remediation summary (optional):

docker run --rm -v "$(pwd):/repo:ro" -e OPENAI_API_KEY=sk-... $IMAGE scan /repo

SARIF for GitHub Advanced Security / IDE integration:

docker run --rm -v "$(pwd):/repo:ro" $IMAGE \
  scan /repo --format sarif > results.sarif

Incremental PR-style scan (changed files only):

pnpm segrep scan . --changed-only --base-ref main

Policy-as-code

Add .segrep/policy.yml in the repo root to configure fail thresholds, scanner selection, CVE allowlists, and ignored paths. See segrep-policy.example.yml.


CI integration

GitHub Actions

name: Security scan

on:
  pull_request:
  push:
    branches: [main]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run security scanner
        run: |
          docker run --rm -v "${{ github.workspace }}:/repo:ro" \
            ghcr.io/szaranger/security-scanner:latest \
            scan /repo --format json --fail-on high

Save JSON as an artifact:

      - name: Run security scanner
        run: |
          docker run --rm -v "${{ github.workspace }}:/repo:ro" \
            ghcr.io/szaranger/security-scanner:latest \
            scan /repo --format json --fail-on high > scan-results.json

      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: security-scan
          path: scan-results.json

GitLab CI

security-scan:
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker pull ghcr.io/szaranger/security-scanner:latest
    - |
      docker run --rm -v "${CI_PROJECT_DIR}:/repo:ro" \
        ghcr.io/szaranger/security-scanner:latest \
        scan /repo --format json --fail-on high

Generic (any CI with Docker)

  1. Check out the repo.
  2. Mount the workspace at /repo:ro.
  3. Run scan /repo --format json --fail-on high.
  4. Use the exit code for pass/fail.

Requirements

RequirementNotes
DockerOnly dependency for users
Network (first run)Scanners download vulnerability rules and configs on first use
Volume mountTarget code must be mounted read-only into the container

No Postgres, API keys, or signup.


JSON output shape

With --format json, stdout includes:

{
  "result": {
    "findings": [...],
    "scannedAt": "...",
    "scanners": ["deps-cves", "trivy", "semgrep", "syft", "gitleaks", "checkov"],
    "scannerVersions": { "trivy": "0.58.2" },
    "sbom": {
      "path": ".segrep/sbom.cyclonedx.json",
      "format": "cyclonedx-json",
      "componentCount": 42
    }
  },
  "severityCounts": { "critical": 0, "high": 4, "medium": 3, "low": 0, "unknown": 0 },
  "summary": {
    "summary": "...",
    "recommendedRemediation": "...",
    "estimatedEffort": "..."
  }
}

sbom is present when Syft or segrep-sbom ran. scannerVersions is included when scanners expose a version. summary is omitted when there are no findings or no OPENAI_API_KEY is set.

Future enhancement: run Trivy against the Syft SBOM for dependency CVE coverage from the generated bill of materials (not implemented yet).


Troubleshooting

IssueFix
Path does not existMount the repo at /repo and pass scan /repo
Slow first scanNormal — scanners download DBs; cache Docker layers in CI if possible
Permission denied on mountEnsure the path exists and Docker can read it
Empty findings on known-vulnerable projectTry --scanners all; check mount path
CI fails unexpectedlyConfirm --fail-on threshold; inspect JSON output

Platform (optional)

Need scan history, a dashboard, or GitHub PR comments? That’s a separate hosted platform tier:

Scanner-only users can ignore the platform docs entirely.


Publishing releases

Maintainers tag a release to publish to GitHub Container Registry:

git tag v0.1.0
git push origin v0.1.0

See .github/workflows/docker-publish.yml.