Broly
A berserker code security scanner.
Secrets · SCA · SAST in a single binary.
AI-powered. No rule files. No rule engine.
What It Does
Broly runs three security scanners in parallel on your codebase and delivers results in seconds:
| 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 · no rule files, no rule engine |
Always-on · data flow analysis · CVSS scoring |
Install
Go install (any platform):
go install github.com/Shasheen8/Broly/cmd/broly@latest
Linux - pre-built binary from Releases.
macOS - build from source with Hyperscan (faster secrets scanning):
brew install vectorscan
git clone https://github.com/Shasheen8/Broly.git
cd Broly && make build
[!TIP]
go install uses pure Go regex for secrets. The source build enables Hyperscan via -tags vectorscan for significantly faster pattern matching on large codebases.
SAST / AI features require a Together AI key:
export TOGETHER_API_KEY=your_key_here
Usage
broly scan # run all scanners on 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 triage suggestions
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
broly scan --ai-model Qwen/Qwen3-Coder-Next-FP8 # override model (default)
# Outputs
broly scan -f json # JSON output
broly scan -f sarif -o results.sarif # SARIF for GitHub Code Scanning
broly scan --min-severity high # only high and critical
broly scan --sca --offline # skip OSV API lookup
# Scan 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 SAST on unchanged files (uses .broly-cache.json)
broly scan --quiet # suppress progress output
Config file
[!TIP]
.broly.yaml is loaded automatically from the repo root. CLI flags always override it. See .broly.yaml for a working example.
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. See .broly-baseline.yaml for a working example.
suppress:
- fingerprint: "abc123..." # silence accepted risk / known FP
reason: "test fixture"
require:
- rule_id: "SQL-INJECTION"
file: "api/handlers.py"
description: "SQL injection in user lookup - must be detected"
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.
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
Output Results
AI Triage - verdict and fix per finding
--ai-triage labels each finding TRUE/FALSE positive with a confidence score and attaches a fix. Add --explain for a one-sentence attack scenario:
▸ SAST (2 findings)
SEVERITY ISSUE FILE DESCRIPTION
──────────────────────────────────────────────────────────────────────────────────────────────────
CRITICAL SQL injection via unsanitize.. api/handlers.py:10 SQL injection via unsaniti..
🔺 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
SAST - AI-powered code analysis
broly vdev - scanning api/handlers.py
scanners: sast | workers: 8
▸ SAST (4 findings)
SEVERITY ISSUE FILE DESCRIPTION
──────────────────────────────────────────────────────────────────────────────────────────────────
CRITICAL SQL injection via unsanitize.. api/handlers.py:10 SQL injection via unsaniti..
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..
Each file is sent directly to Qwen/Qwen3-Coder-Next-FP8 with a structured security prompt. The model traces data flow from source to sink, infers CVSS scores, and finds what static rules miss.
Secrets - with AI false positive filtering
Without --ai-filter-secrets (raw regex hits):
▸ 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
With --ai-filter-secrets (AI reads surrounding context):
✔ No findings detected. Clean scan!
The AI recognized the file contained documented placeholder values (EXAMPLE in variable names, "Test / dummy values" comment) and filtered them all as false positives, reducing noise to zero.
SCA - dependency vulnerability scan
broly vdev - scanning /path/to/project
scanners: sca | workers: 8
▸ SCA (13 findings)
SEVERITY VULN ID PACKAGE VERSION FIXED ECOSYSTEM
──────────────────────────────────────────────────────────────────────────────────────────────────
MEDIUM GHSA-9hjg-9r4m-mvj7 requests 2.31.0 no fix PyPI
MEDIUM GHSA-496j-2rq6-j6cc grpcio 1.54.0 no fix PyPI
MEDIUM GHSA-cfgp-2977-2fmm grpcio 1.54.0 no fix PyPI
MEDIUM GHSA-wh2j-26j7-9728 google-cloud-ai 1.25.0 no fix PyPI
MEDIUM GHSA-7gcm-g887-7qv7 protobuf 3.20.3 no fix PyPI
...
╔══════════════════════════════════════════════════════╗
║ ║
║ 13 total findings ║
║ Critical 0 High 0 Medium 13 Low 0 ║
║ duration: 388ms ║
║ ║
╚══════════════════════════════════════════════════════╝
Add --ai-sca-reachability to check whether the vulnerable functions are actually called in your code. Unreachable findings are automatically downgraded one severity level and tagged [Unreachable].
What Gets Scanned
Secrets - 487 rules across:
AWS, GitHub, OpenAI, Anthropic, GCP, Azure, Cloudflare, Slack, Stripe, Twilio,
SendGrid, Docker, npm, SSH/PGP/RSA/EC keys, database URIs, JWTs, generic tokens
SCA - 19 ecosystems, 50+ lockfile formats:
Go, Python, JavaScript, Ruby, Rust, Java, PHP, .NET, Dart, C/C++, Haskell,
Elixir, Erlang, R, Swift, Lua, Nim, OCaml, Julia
SAST - AI analysis across 18 languages. No rule files. No rule engine. No maintenance:
Go, Python, JavaScript, TypeScript, Java, Ruby, PHP, C#, Rust, C, C++,
Kotlin, Swift, Bash, and more
| Format |
Flag |
Use case |
| Table (default) |
-f table |
Terminal, human review |
| JSON |
-f json |
CI pipelines, tooling |
| SARIF 2.1.0 |
-f sarif |
GitHub Code Scanning |
Acknowledgments
License
MIT