Broly

module
v0.1.53 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2026 License: MIT

README

Broly

Broly

A berserker code security scanner.

Secrets · SCA · SAST in a single binary.

AI-powered. No rule files. No rule engine.

Go License Release Together AI


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

Output Formats

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

Directories

Path Synopsis
cmd
broly command
pkg
ai
Package ai provides a shared Together.ai client for all Broly scanners.
Package ai provides a shared Together.ai client for all Broly scanners.
cache
Package cache provides a file-hash cache for incremental scanning.
Package cache provides a file-hash cache for incremental scanning.
sast
Package sast provides AI-powered static application security testing.
Package sast provides AI-powered static application security testing.
sca
Package sca adapts osv-scalibr + osv.dev to Broly's core.Scanner interface.
Package sca adapts osv-scalibr + osv.dev to Broly's core.Scanner interface.
secrets
Package secrets adapts Titus's engine to Broly's core.Scanner interface.
Package secrets adapts Titus's engine to Broly's core.Scanner interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL