Security-analysis CLI that detects project languages, plans compatible scanners, normalizes and deduplicates their output, optionally validates high-priority findings with AI, and generates technical, management, and bug-bounty reports.
“Zero-day” findings are hypotheses, not proof of a previously unknown vulnerability. Always reproduce and manually review them before disclosure.
- Go 1.24+
- One or more scanners on
PATH. Language-aware selection supports Semgrep, Bandit, GoSec, ESLint, SpotBugs, PHPStan, Psalm, Cargo Audit, Brakeman, Slither, OWASP Dependency-Check, and Clang Analyzer. - Anthropic API key or a running 9Router instance for AI validation. AI remains optional; scanning degrades gracefully when unavailable.
Some scanners also require their language toolchain. For example, cargo-audit requires Cargo, Slither requires Python, Foundry-based Solidity projects may require forge, ESLint requires Node.js/npm, and Clang Analyzer requires LLVM/Clang. A report may still be exported when scanners are skipped, so always review the scanner-plan and degraded-mode messages in the console.
pip install semgrep
pip install bandit
go install github.com/securego/gosec/v2/cmd/gosec@latest
export ANTHROPIC_API_KEY=replace-meFrom the analyzer repository, install dependencies and verify the build:
go mod download
go test ./...
go build -o analyzer.exe ./cmd/analyzerScan a source directory using the default policy:
.\analyzer.exe --target "C:\path\to\project" --output report.jsonAlternatively, run without building a binary:
go run ./cmd/analyzer/main.go --target /absolute/path/to/project --output report.jsonThe older positional form remains supported:
.\analyzer.exe "C:\path\to\project"Scan source code plus an authorized running application:
.\analyzer.exe --target "C:\path\to\project" `
--dast-url "https://staging.example.com" `
--export-format json,html,sarif `
--output report.jsonThe CLI writes report.json in the current directory. Configure scanner timeouts, model, confidence threshold, workers, and token budget in config/config.yaml.
The optional DAST URL enables a passive, non-mutating HTTP baseline scan for HTTPS, cookie flags, and response security headers. Only scan systems you own or are explicitly authorized to assess.
The detector recognizes Go, Python, JavaScript/TypeScript, Java, C/C++, PHP, Rust, Ruby, .NET, Swift, Kotlin, and Solidity projects. Foundry dependencies under lib/ are excluded from language planning; Slither still resolves them while compiling the Solidity project. Polyglot repositories are supported and scanners are deduplicated through a bounded worker pool.
Copy .env.example to .env; the analyzer loads it automatically before YAML configuration and scanner planning:
Copy-Item .env.example .env
.\analyzer.exe --target "C:\path\to\project" --output report.jsonWith ANALYZER_AUTO_INSTALL=true, the environment manager attempts to install supported missing scanners. The relevant package manager or toolchain must already exist; for example, Cargo must be installed before cargo-audit can be installed. Set ANALYZER_AI_ENABLED=false for a scanner-only run. Existing shell variables override .env. Set ANALYZER_ENV_FILE to use another environment file. Platform toolchains such as Foundry/forge and LLVM still need to be installed through their official installers; common per-user locations such as ~/.foundry/bin are discovered automatically.
Keep ANALYZER_AUTO_INSTALL=false when scanning repositories you do not fully trust. The analyzer inspects installation hints in the target's own README to decide what to auto-install — that content is untrusted. Every recognized line is re-validated against a strict allowlist (see "Sandboxed scanning" below) and is never executed on the host: with ANALYZER_AUTO_INSTALL=true, it only proceeds when the corresponding tool is available through a sandboxed Docker image, and refuses otherwise rather than falling back to a local install.
By default, scanners run directly on the host, with their working directory set to the (untrusted) target repository. Several of them execute code or configuration that lives inside that repo — ESLint plugins, PHPStan/Psalm bootstrap files, Cargo build scripts via cargo audit, Foundry forge via Slither, clang/scan-build compiling the target's own build. Set sandbox.enabled: true in config/config.yaml (or ANALYZER_SANDBOX_ENABLED=true) to run scanners that have a configured Docker image inside a locked-down container instead: read-only mount of the target, --network none by default, dropped capabilities, no privilege escalation, and resource limits. Requires Docker.
Today, images are configured for semgrep, bandit, gosec, and slither (sandbox.images in config/config.yaml; semgrep uses the official returntocorp/semgrep image, the other three have first-party Dockerfiles under docker/sandbox/). Any other scanner without a configured image still runs locally, unsandboxed, exactly as before — this is a deliberate, incremental rollout, not a claim that every scanner is isolated. None of these images have been built or run against a real Docker daemon while developing this feature; verify them yourself (docker/sandbox/README.md) before relying on them. See that same file to add coverage for another scanner.
The README-driven auto-install feature (above) is the one place a string parsed out of the target repository reaches process execution, so it has no local fallback at all: with sandboxing unavailable, ANALYZER_AUTO_INSTALL=true simply skips that tool rather than installing it on the host.
The default provider is Anthropic. Configure its key in the environment:
$env:ANTHROPIC_API_KEY = "your-key"
.\analyzer.exe --target "C:\path\to\project"To route AI validation and remediation through 9Router, install and start it:
npm install -g 9router
9router9Router normally listens on http://localhost:20128. Connect providers in its dashboard, then discover the available model IDs:
Invoke-RestMethod http://localhost:20128/v1/modelsSet the analyzer environment variables and run a scan:
$env:ANALYZER_AI_PROVIDER = "9router"
$env:NINEROUTER_URL = "http://localhost:20128"
$env:NINEROUTER_MODEL = "cc/claude-opus-4-6"
$env:NINEROUTER_KEY = "your-9router-api-key" # Omit when local API-key auth is disabled.
.\analyzer.exe --target "C:\path\to\project" `
--policy policies/default.yaml `
--export-format json,html,sarifIt can also be configured persistently in config/config.yaml:
ai:
provider: "9router"
ninerouter:
base_url: "http://localhost:20128"
api_key: ""
model: "cc/claude-opus-4-6"
max_retries: 3
timeout_seconds: 60
health_check: trueNINEROUTER_KEY is preferred over storing a key in YAML. Never commit .env or real API keys. If a key has entered Git history, remove it and rotate it before publishing the repository. Model IDs depend on the providers and combos configured in your 9Router dashboard; use the exact ID returned by /v1/models.
The analyzer also provides native secret detection with redacted evidence, CVSS v3.1 scoring, local and optional Claude-powered remediation, OWASP/CWE/compliance mapping, custom YAML policies, SQLite history, container scanning through Trivy or Grype, and CycloneDX/SPDX SBOM generation.
Export all supported report formats (html is the offline interactive business report; dashboard emits a separate .dashboard.html copy):
go run ./cmd/analyzer/main.go --target ./project \
--policy policies/default.yaml \
--export-format json,html,dashboard,pdf,sarif,xml,csv \
--output report.jsonGenerate a bug-bounty submission bundle (JSON, Markdown, HTML, PDF, and plaintext):
.\analyzer.exe --target "C:\path\to\project" `
--policy policies/default.yaml `
--export-format json,html,sarif,bounty-report `
--bounty-program yeswehack `
--output report.jsonSupported bounty adapters are hackerone, bugcrowd, intigriti, yeswehack, and federacy. With --output report.json, the bundle uses names such as report.bounty.json, report.bounty.md, report.bounty.html, report.bounty.pdf, and report.bounty.txt.
The bounty quality gate filters ineligible candidates and does not treat static scanner output as submission-ready evidence. An empty bundle is valid and means no finding passed the current eligibility checks. Generated items remain human-review drafts; verify the exact vulnerable asset, program scope, runtime reproduction, impact, and evidence before submission. POCs use non-destructive markers and must only be run with written authorization. The analyzer does not submit reports to a bounty platform.
History and SBOM:
go run ./cmd/analyzer/main.go --target ./project \
--track-history --database analyzer.db \
--generate-sbom cyclonedxCompare the new scan with a stored report:
go run ./cmd/analyzer/main.go --target ./project \
--track-history --compare-with scan-previous-idContainer images must be provided explicitly:
go run ./cmd/analyzer/main.go --target ./project \
--scan-containers docker.io/library/nginx:latestGenerate CI/CD files inside the target repository:
go run ./cmd/analyzer/main.go --target ./project --github-actions
go run ./cmd/analyzer/main.go --target ./project --gitlab-ci
go run ./cmd/analyzer/main.go --target ./project --jenkins
go run ./cmd/analyzer/main.go --target ./project --pre-commitGeneration flags write files into the target repository. The pre-commit hook blocks commits only when the generated report contains critical findings.
On Linux/macOS, install package-manager-based scanners with:
bash tools/install_dependencies.shTarget documentation may be inspected for scanner installation hints when automatic installation is enabled. As described under "Sandboxed scanning" above, this no longer executes anything on the host: it only confirms the referenced tool (semgrep, bandit, or gosec) is available via its sandboxed Docker image, and skips it otherwise. Still review the console output, and remember that scanners without a configured sandbox image run unsandboxed on the host as before — prefer a disposable VM or container for those when the target repository isn't fully trusted.
- Scanners run concurrently with deadlines and normalize their JSON into a common finding model.
- Known fixtures and duplicates are removed before any API call.
- High-priority findings are trimmed to the configured estimated token budget and validated in batches of at most ten.
- Local anomaly rules inspect source files for custom crypto, validation/auth bypass, unsafe shared state, and business-logic manipulation.
- The JSON report includes CVSS estimates, CWE/MITRE mapping, remediation, AI rationale, confidence, and possible exploit-chain links.
The AI stage sends finding metadata and code snippets to the selected provider. When using 9Router, its configured upstream provider may receive that content. Do not enable AI validation for source prohibited by your data-handling policy. Model-generated assessments may be incorrect.