What It Does
| Scanner |
Engine |
AI Layer |
| Secrets |
Titus · 487 rules · Hyperscan |
--ai-filter-secrets eliminates false positives |
| SCA |
osv-scalibr + osv.dev · 19 ecosystems |
--ai-sca-reachability checks if the vuln is actually called |
| SAST |
Together AI · Qwen/Qwen3-Coder-Next-FP8 |
Source-to-sink data flow · CVSS scoring |
| Dockerfile |
AI-powered · Dockerfile, Containerfile, Compose |
Privilege escalation, secret exposure, dangerous mounts |
| Container |
go-containerregistry + osv.dev · Alpine, Debian, Ubuntu, RHEL |
OS package CVEs with layer attribution |
Install
go install github.com/Shasheen8/Broly/cmd/broly@latest
Pre-built Linux binaries on Releases. macOS: build from source with brew install vectorscan && make build for Hyperscan support.
SAST and AI features require export TOGETHER_API_KEY=your_key_here.
Usage
broly scan # all scanners, current directory
broly scan /path/to/project # specific path
# individual scanners
broly scan --secrets # secrets only
broly scan --sca # SCA only
broly scan --sast # SAST only (requires TOGETHER_API_KEY)
# AI enhancements
broly scan --ai-filter-secrets # filter secrets false positives with AI
broly scan --ai-sca-reachability # check if vulnerable deps are actually called
broly scan --ai-triage # verdict (TP/FP) + fix suggestion per finding
broly scan --ai-triage --explain # + concise attack-scenario sentence per finding
# container scanning
broly scan --container alpine:3.19 # scan a container image for vulnerabilities
broly scan --container ./image.tar # scan from tarball
# output
broly scan -f json # JSON output
broly scan -f sarif -o results.sarif # SARIF 2.1.0 for GitHub Code Scanning
broly scan --min-severity high # only high and critical
# config
broly scan --config .broly.yaml # load project config file
broly scan --baseline .broly-baseline.yaml # suppress known FPs / require specific findings
broly scan --incremental # skip unchanged files (uses .broly-cache.json)
Scanner Output
SAST
Each file is sent to the LLM with a structured security prompt. The model traces data flow from source to sink, infers CVSS scores, and finds what static rules miss.
▸ SAST (4 findings)
SEVERITY ISSUE FILE DESCRIPTION
──────────────────────────────────────────────────────────────────────────────────────────────────
CRITICAL SQL injection via unsanitize.. api/handlers.py:10 User input flows directly ..
CRITICAL OS command injection via uns.. api/handlers.py:15 OS command injection via u..
HIGH Path traversal in read_file api/handlers.py:20 Path traversal in read_fil..
HIGH Insecure deserialization via.. api/handlers.py:25 Insecure deserialization v..
Dockerfile and Compose
Auto-detected during normal scans. Specialized prompts cover privilege escalation, hardcoded secrets, dangerous mounts, unpinned base images, and more.
▸ DOCKERFILE (4 findings)
SEVERITY ISSUE FILE DESCRIPTION
──────────────────────────────────────────────────────────────────────────────────────────────────
CRITICAL Hardcoded secrets in ENV/ARG Dockerfile:3 Secrets visible in image hi..
CRITICAL Docker socket mounted docker-compose.yml:14 Full control over Docker da..
HIGH curl piped to bash Dockerfile:10 Compromised script runs as ..
MEDIUM Running as root (no USER) Dockerfile:1 Increases blast radius of a..
Secrets
487 rules. --ai-filter-secrets reads surrounding code context and eliminates placeholders and test values:
▸ SECRETS (3 findings)
SEVERITY RULE FILE REDACTED
──────────────────────────────────────────────────────────────────────────────────
HIGH AWS API Key config/example.py:6 AKIA****MPLE
HIGH AWS API Credentials config/example.py:6 AKIA****KEY"
HIGH GitHub Personal Access Token config/example.py:9 ghp_****8B4a
SCA
19 ecosystems, 50+ lockfile formats. --ai-sca-reachability checks if the vulnerable function is actually called:
▸ SCA (3 findings)
SEVERITY VULN ID PACKAGE VERSION FIXED ECOSYSTEM
──────────────────────────────────────────────────────────────────────────────────────────────────
MEDIUM GHSA-9hjg-9r4m-mvj7 requests 2.31.0 no patch PyPI
MEDIUM GHSA-496j-2rq6-j6cc grpcio 1.54.0 no patch PyPI
MEDIUM GHSA-cfgp-2977-2fmm grpcio 1.54.0 no patch PyPI
Container
--container pulls an image, extracts OS packages, and matches against OSV. Each finding shows which layer introduced it:
▸ CONTAINER (5 findings)
SEVERITY VULN ID PACKAGE VERSION FIXED ECOSYSTEM LAYER
────────────────────────────────────────────────────────────────────────────────────────────────────────────────
MEDIUM ALPINE-CVE-2023-42.. busybox 1.36.1-r2 no patch Alpine:v3.18 base
MEDIUM ALPINE-CVE-2025-26.. musl 1.2.4-r1 no patch Alpine:v3.18 base
AI Triage
--ai-triage labels each finding TRUE/FALSE positive with a confidence score and a fix. For container/SCA findings with no patch, it suggests mitigations. --explain adds a one-sentence attack scenario:
CRITICAL SQL injection via unsanitize.. api/handlers.py:10 User input flows directly ..
🔺 TRUE_POSITIVE [HIGH] User input flows directly into raw SQL query without parameterization
An attacker sends id=1 OR 1=1 to dump the entire users table.
fix:
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))
HIGH Path traversal in read_file api/handlers.py:20 Path traversal in read_fil..
🟢 FALSE_POSITIVE [HIGH] File path is validated against an allowlist before use
Developer Feedback Loop
Check a box in the PR comment to mark a finding as a false positive. Broly verifies write access, commits the fingerprint to .broly-baseline.yaml, and the finding never surfaces again.
- [ ] 🔴 CRITICAL · SQL injection in get_user() · api/handlers.py:7
Suppressions accumulate over time; each repo builds its own false positive memory.
Configuration
Config file
[!TIP]
.broly.yaml is loaded automatically from the repo root. CLI flags always override it.
min_severity: low
exclude_paths:
- vendor
- .git
workers: 8
Baseline
[!NOTE]
suppress silences known false positives. require asserts specific findings must be detected every scan; missing entries cause a non-zero exit.
suppress:
- fingerprint: "abc123..."
reason: "test fixture"
require:
- rule_id: "SQL-INJECTION"
file: "api/handlers.py"
reason: "SQL injection in user lookup - must be detected"
Inline suppression
query = "SELECT * FROM users WHERE id = " + user_id # broly:ignore
query = f"SELECT * FROM users WHERE id = {user_id}" # broly:ignore SQL-INJECTION
Acknowledgments
| Project |
Role |
| Titus |
Secrets engine: 487 rules, Hyperscan + Go regex |
| osv-scalibr |
Lockfile extraction across 50+ formats |
| osv.dev |
Vulnerability database by Google |
| go-containerregistry |
Container image pulling and layer inspection |
| Together AI |
AI inference for SAST, triage, and reachability |
License
MIT. See LICENSE for the full text.