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:latestUntil then, build from source:
git clone https://github.com/szaranger/security.git
cd security
pnpm docker:build
# image tag: security-scanner:localSet 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 /repoScan with CI exit code (fail on high+)
docker run --rm -v "$(pwd):/repo:ro" $IMAGE \
scan /repo --format json --fail-on highExit code 1 when findings meet the threshold; 0 otherwise.
What you get
| Scanner | Finds |
|---|---|
| deps-cves | Dependency CVEs from OSV with GHSA/CVE alias mapping for npm lockfile packages |
| Trivy | Dependency CVEs, misconfigurations in manifests/lockfiles |
| Semgrep | Code patterns, insecure APIs, SAST-style issues |
| Syft | Software bill of materials (CycloneDX JSON artifact) |
| Gitleaks | Hardcoded secrets, API keys, tokens |
| Checkov | Terraform, 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 remediationjson— 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]| Flag | Default | Description |
|---|---|---|
path | . | Directory inside the container (usually /repo) |
--format | terminal | terminal, json, or sarif |
--scanners | all registered scanners | Comma-separated list or all |
--changed-only | off | Limit findings to files changed vs --base-ref |
--base-ref | main | Base git ref for --changed-only |
--fail-on | none | Exit 1 if findings at or above this severity (overridden by .segrep/policy.yml) |
--target-url | — | Required for ZAP and segrep-dast. DAST target URL (opt-in; authorized targets only) |
--kubeconfig | — | Kubeconfig path for Kubescape cluster scans |
--aws-profile | — | AWS 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:4010See 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(defaultauto)SEGREP_SBOM_PARITY_SHADOW=trueto compare local output against external Syft and write.segrep/segrep-sbom-parity.json
segrep-vuln environment variables:
SEGREP_VULN_MODE=auto|local|external(defaultauto)SEGREP_VULN_PARITY_SHADOW=trueto 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(defaultauto)SEGREP_DAST_PARITY_SHADOW=trueto compare local findings against external ZAP and write.segrep/segrep-dast-parity.jsonSEGREP_DAST_TIMEOUT_MSfor request timeoutSEGREP_DAST_USER_AGENTto override the default user agentSEGREP_DAST_DISCLOSURE_PATHSfor 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 trivyJSON to a file:
docker run --rm -v "$(pwd):/repo:ro" $IMAGE \
scan /repo --format json > scan-results.jsonAll scanners:
docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners allSBOM 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 jsonDAST (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.comLicense 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 highKubernetes manifests (no cluster required):
docker run --rm -v "$(pwd):/repo:ro" $IMAGE scan /repo/k8s --scanners kubescapeAWS posture (read-only credentials via env):
docker run --rm -e AWS_PROFILE=readonly -v "$(pwd):/repo:ro" $IMAGE scan /repo --scanners prowlerCloud 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-iacAI remediation summary (optional):
docker run --rm -v "$(pwd):/repo:ro" -e OPENAI_API_KEY=sk-... $IMAGE scan /repoSARIF for GitHub Advanced Security / IDE integration:
docker run --rm -v "$(pwd):/repo:ro" $IMAGE \
scan /repo --format sarif > results.sarifIncremental PR-style scan (changed files only):
pnpm segrep scan . --changed-only --base-ref mainPolicy-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 highSave 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.jsonGitLab 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 highGeneric (any CI with Docker)
- Check out the repo.
- Mount the workspace at
/repo:ro. - Run
scan /repo --format json --fail-on high. - Use the exit code for pass/fail.
Requirements
| Requirement | Notes |
|---|---|
| Docker | Only dependency for users |
| Network (first run) | Scanners download vulnerability rules and configs on first use |
| Volume mount | Target 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
| Issue | Fix |
|---|---|
Path does not exist | Mount the repo at /repo and pass scan /repo |
| Slow first scan | Normal — scanners download DBs; cache Docker layers in CI if possible |
| Permission denied on mount | Ensure the path exists and Docker can read it |
| Empty findings on known-vulnerable project | Try --scanners all; check mount path |
| CI fails unexpectedly | Confirm --fail-on threshold; inspect JSON output |
Platform (optional)
Need scan history, a dashboard, or GitHub PR comments? That’s a separate hosted platform tier:
- vercel-neon-local-worker.md — dashboard + API on Vercel, Neon Postgres, local/Docker worker
- docker.md — same image also runs
workermode for the platform
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.0See .github/workflows/docker-publish.yml.