๐ฅ HERETIC
Autonomous AI agent that finds business-logic vulnerabilities
The bug class scanners can't touch โ and human pentesters still find by hand.
Quickstart ยท Install ยท Commands ยท Config ยท Bug classes ยท How it works ยท Safety ยท FAQ
Heretic (n.) โ one who breaks the sacred rules. This tool breaks the rules an application assumes but never enforces.
HERETIC is a CLI tool (in the spirit of nmap, sqlmap, nuclei) that reasons about an app's business intent, then systematically tries to violate it: IDOR/BOLA, broken function-level auth, excessive data exposure, price tampering, workflow bypass, mass assignment, race conditions.
It is not another signature scanner. Signature scanners find XSS / SQLi / CVEs. HERETIC finds the ~70% of critical web bugs that have no signature โ where the code did exactly what it was told, but what it was told violated the business rules. It reasons about intent with an LLM, but never trusts the LLM to confirm a bug โ a deterministic Oracle proves every finding, which is why the false-positive rate is ~0%.
heretic scan -u https://target.local --roe roe.yaml --accounts accounts.yaml
๐ See it work โ real output, live OWASP Juice Shop
Real recording โ offline FP-gate, then live Juice Shop and VAmPI. Reproduce with scripts/demo.sh ยท replay the raw cast with asciinema play docs/demo/heretic-demo.cast.
Not a mock-up. This is HERETIC against a live bkimminich/juice-shop container โ model auto-detected, basket id harvested from the login response, attack surface discovered from the SPA's JS bundle.
CONFIRM excessive_data_exposure โ basketitem list leaks all users' records
CONFIRM bfla โ admin function /rest/admin/application-configuration is exposed to unauthenticated users
CONFIRM mass_assignment โ registration at /api/Users accepts privileged field 'role'
CONFIRM price_tamper โ /api/BasketItems accepts a negative quantity (-100)
CONFIRM workflow_bypass โ order finalized at /rest/basket/6/checkout without a payment step
โโโโโโโโโโโโโโโโโโ 7 confirmed ยท 17 dropped (false positives) โโโโโโโโโโโโโโโโโโโ
Five business-logic classes confirmed on a live app in one command โ with 0 false positives. The 17 "dropped" are candidates the Oracle refused to confirm (SPA catch-alls, public catalogs, the LLM's wrong guesses). Every confirmation is deterministic and reproducible.
It even catches itself hallucinating โ when the LLM invents an endpoint that isn't on the target, HERETIC detects it and regenerates grounded on the real surface:
Phase 3b hypotheses โ logic classes (LLM + knowledge)
โ hallucination detected โ 1/3 test(s) referenced endpoints not on the real surface (33%); regenerating grounded
โ self-corrected โ added 3 grounded test(s)
โ Validation
Two independent proofs โ one you can run right now, one you can reproduce against real targets.
Offline โ every build, no key, no network (heretic bench, wired into CI):
| Metric | Result |
|---|---|
| Test suite | 126 passing |
| Precision ยท Recall | 100% ยท 100% |
| False-positive rate | 0% |
Live โ reproducible with heretic livecheck (the read-only classes need no LLM key):
| Target | BOLA mechanism | Result |
|---|---|---|
| crAPI | autonomous discovery โ listโdetail probing โ /vehicle/{id}/location |
confirmed ยท 0 FP |
| OWASP Juice Shop | login-response basket-id harvest โ /rest/basket/{id}, plus a 5-class sweep (data-exposure ยท BFLA ยท mass-assignment ยท price-tamper ยท workflow-bypass) |
7 confirmed ยท 0 FP |
| VAmPI | owner-aware harvest of a leaky list โ /books/v1/{title} |
confirmed ยท 0 FP |
Coverage today: 9 business-logic classes โ 7 fully mechanical + coupon_abuse (deterministic) + auth_flow (LLM-driven). Login auto-detection spans JSON/JWT ยท session-cookie ยท CSRF-guarded ยท form-encoded flows.
Offline metrics are checked on every commit. The live numbers reproduce from the profiles in
targets/โ seedocs/09-LIVE-VALIDATION.md. Real-world FP on hardened production apps is not yet independently measured;~0%reflects the three deliberately-vulnerable targets above.
๐ Why HERETIC wins
| HERETIC | Signature scanners (Burp / ZAP / nuclei) |
Generic "AI pentest" wrappers |
|
|---|---|---|---|
| Finds business-logic bugs (BOLA, price, workflowโฆ) | โ core mission | โ no signature exists | โ ๏ธ guesses |
| False-positive rate | ~0% (Oracle-proven) | high โ manual triage | high โ LLM hallucination |
| Proves a bug actually happened | โ deterministic proof | N/A (pattern match) | โ "the model thinks so" |
| Reproducible PoC per finding | โ every finding | partial | rare |
| Autonomous attack-surface discovery | โ OpenAPI ยท JS ยท browser ยท probe | manual / crawl | varies |
| Runs with no API key | โ deterministic classes | โ | โ needs an LLM |
| Chains primitives โ higher impact | โ takeover / fraud / exfil | โ | โ |
| CI-ready (SARIF, fail-on, Action) | โ | โ | โ |
The one-liner: signature scanners find bugs that have a pattern; the ~70% of critical web bugs that don't โ the logic flaws โ need reasoning about intent. HERETIC reasons with an LLM but proves with deterministic code, so it gets the logic coverage of a human without the false positives of an AI toy.
๐ Table of contents
- Validation
- Why HERETIC wins
- Install
- Quickstart (60 seconds)
- The three ways to run it
- Command reference
- Choosing an AI model
- Configuration
- What it finds (bug classes)
- How it works
- Output & reporting
- Run it in CI
- Safety & legal
- FAQ
- Docs
๐ฆ Install
Requirements: Python 3.11+. An AI key is optional (see models) โ HERETIC runs the deterministic classes with no key at all.
| Method | Command | When |
|---|---|---|
| pipx (recommended) | pipx install heretic-agent | Global CLI, isolated env |
| pip (from source) | pip install -e ".[dev]" | Hacking on it / running tests |
| Docker | docker build -t heretic . && docker run --rm heretic --help | Zero local Python setup |
Optional extras (install only what you need):
pip install -e ".[browser]" # headless-browser XHR capture (Playwright) โ for JS-heavy SPAs
pip install -e ".[gemini]" # the gemini-flash backend
pip install -e ".[rag]" # swap keyword knowledge store for embeddings (ChromaDB)
Verify the install:
heretic version
heretic bench # offline self-test โ no network, no API key. Should report FP-rate 0%.
๐ฅ๏ธ Platform setup โ Windows / macOS / Linux
Step-by-step for each OS. Pick your tab.
๐ช Windows (PowerShell)
# 1. Install Python 3.11+ (skip if you have it)
winget install Python.Python.3.12
# 2. Install HERETIC in an isolated environment
py -m pip install --user pipx
py -m pipx ensurepath # then reopen PowerShell
pipx install heretic-agent
# 3. (optional) Give it an AI key โ this shell only
$env:NVIDIA_API_KEY = "nvapi-xxxxxxxx"
# โฆor persist across shells (reopen the terminal after):
setx NVIDIA_API_KEY "nvapi-xxxxxxxx"
# 4. Confirm the setup (does the key actually work?)
heretic doctor --ping
# 5. Run it
heretic connect
cmd.exe (not PowerShell)? Set the key with
set NVIDIA_API_KEY=nvapi-xxxxxxxx(this shell) orsetx NVIDIA_API_KEY "nvapi-xxxxxxxx"(persistent). Everything else is identical. On Windows Terminal / VS Code terminal, the emoji/box-drawing output renders best โ plaincmd.exeworks too, just less pretty.
From source instead:
git clone https://github.com/SYCO7/heretic.git
cd heretic
py -m venv .venv
.\.venv\Scripts\Activate.ps1 # if blocked: Set-ExecutionPolicy -Scope Process RemoteSigned
pip install -e ".[dev]"
heretic version
If
hereticisn't found afterpipx install, reopen the terminal (pipx just added it to PATH), or runpy -m heretic.cli.
๐ macOS (zsh)
# 1. Install Python 3.11+ and pipx via Homebrew
brew install python@3.12 pipx
pipx ensurepath # then reopen Terminal
# 2. Install HERETIC
pipx install heretic-agent
# 3. (optional) AI key โ add the export line to ~/.zshrc to persist
export NVIDIA_API_KEY="nvapi-xxxxxxxx"
# 4. Run it
heretic connect
From source instead:
git clone https://github.com/SYCO7/heretic.git && cd heretic
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
heretic version
Fully private / local model:
brew install ollama
ollama serve & # start the daemon
ollama pull qwen2.5:7b # HERETIC auto-selects it โ nothing leaves your Mac
๐ง Linux (bash)
# 1. Python 3.11+ (Debian/Ubuntu shown; use your package manager)
sudo apt install -y python3 python3-venv python3-pip pipx
pipx ensurepath
# 2. Install HERETIC
pipx install heretic-agent
# 3. (optional) AI key โ add to ~/.bashrc to persist
export NVIDIA_API_KEY="nvapi-xxxxxxxx"
# 4. Run it
heretic connect
From source / Docker:
git clone https://github.com/SYCO7/heretic.git && cd heretic
python3 -m venv .venv && source .venv/bin/activate && pip install -e ".[dev]"
# or: docker build -t heretic . && docker run --rm heretic --help
Using
--browser(SPA XHR capture)? After installing the browser extra, fetch the engine once:playwright install chromium(works the same on all three OSes).
Prefer a .env file over shell exports? Drop a .env in your working directory โ HERETIC auto-loads it on every command, on every OS:
NVIDIA_API_KEY=nvapi-xxxxxxxx
โก Quickstart (60 seconds)
The easy path โ no config files to write. Point it at your app, give it two logins, done:
heretic connect
connect will:
- Ask for the target URL and two test accounts.
- Auto-detect the login endpoint and where the token lives in the response (handles OTP / MFA / SSO โ just paste a bearer token when prompted).
- Auto-detect your AI model โ a hosted key or a local Ollama model, whichever is best available.
- Discover the attack surface, run the scan, and print confirmed findings.
Or launch the full interactive menu:
heretic # menu: Connect ยท Auto ยท Doctor ยท Scan ยท Models ยท Keys โฆ
๐ก No AI key and no Ollama? It still runs โ the deterministic classes (BOLA, BFLA, data-exposure) need no LLM and never change state. You get real findings offline.
๐ The three ways to run it
Pick the entry point that matches how much control you want:
1. Guided โ heretic connect / heretic auto
Zero config. Best for a first run or a quick look at an app.
heretic auto -u https://target.local --profile targets/crapi
Runs the whole assessment end-to-end (every class + chaining) and writes an HTML report.
2. Full control โ heretic scan
The scriptable workhorse. You supply roe.yaml + accounts.yaml and choose exactly what runs.
heretic scan -u https://target.local --roe roe.yaml --accounts accounts.yaml \
--discover --chain --iterate 3 --report findings.html
3. Score it โ heretic livecheck
Run against a known target and grade precision / recall / FP vs ground truth. This is how you prove the tool works.
heretic livecheck --profile targets/juiceshop -u http://localhost:3000
๐งญ Command reference
Every command. Run heretic <command> --help for the full flag list.
| Command | What it does |
|---|---|
heretic |
Launch the interactive menu (logo + guided actions) |
heretic connect |
Guided setup โ enter a URL + 2 users, auto-detect login, scan |
heretic auto |
One-command guided scan โ HTML report (auto-detects everything) |
heretic scan |
Full CLI scan โ the main command (see flags below) |
heretic init |
Scaffold starter roe.yaml + accounts.yaml in the current dir |
heretic doctor |
Preflight โ model key(s) set + target reachable (--ping actually calls the model to confirm it works) |
heretic bench |
Offline benchmark (no network / no key) โ scores precision/recall/FP |
heretic livecheck |
Run a profile vs a real target and grade it against ground truth |
heretic resume |
Resume a saved engagement (scan --save) after an interruption |
heretic export |
Turn confirmed attack traces into a fine-tune dataset |
heretic version |
Print version |
heretic scan โ every flag
heretic scan -u <URL> --roe <roe.yaml> --accounts <accounts.yaml> [options]
| Flag | Default | Purpose |
|---|---|---|
-u, --url |
(required) | Target base URL |
--roe |
(required) | Rules-of-engagement YAML (scope + authorization gate) |
--accounts |
(required) | Test-account YAML |
--model |
auto-detect |
Backend id, or auto for per-phase routing (models) |
--classes |
all | Comma list, e.g. bola,price_tamper (classes) |
--mode |
dry-run |
dry-run (read-only) or live (allows state-changing tests) |
--discover / --no-discover |
on if no objects: |
Autonomously find endpoints + infer BOLA targets |
--brute |
off | Also brute-force a path wordlist during discovery (noisy) |
--browser |
off | Headless-browser XHR capture (needs Playwright) |
--chain |
off | Compose confirmed primitives into higher-impact chains |
-i, --iterate <N> |
0 |
On a failed logic test, mutate the input and retry up to N times |
--save <file.db> |
โ | Checkpoint engagement to SQLite (survives Ctrl-C โ resume) |
--log <file.jsonl> |
โ | Append an audit trace (also used for fine-tune export) |
--memory <file.jsonl> |
โ | Learn from + improve across runs |
--report <file.html> |
โ | Write an HTML report |
--sarif <file.sarif> |
โ | Write SARIF 2.1.0 (GitHub/GitLab code scanning) |
--fail-on <sev> |
โ | Exit non-zero if a finding โฅ info|low|medium|high|critical (CI gate) |
-o, --output |
table |
table | json | md |
Copy-paste recipes
# First run against an app you have no config for โ let it discover everything
heretic scan -u https://app.local --roe roe.yaml --accounts accounts.yaml --discover
# Only the read-only classes (safe on production, no LLM key needed)
heretic scan -u https://app.local --roe roe.yaml --accounts accounts.yaml \
--classes bola,bfla,excessive_data_exposure
# Full assessment with chaining, retries, resumable checkpoint + HTML report
heretic scan -u https://app.local --roe roe.yaml --accounts accounts.yaml \
--discover --chain --iterate 3 --save run.db --report findings.html
# JS-heavy Angular/React SPA โ capture the runtime XHRs a static scrape misses
heretic scan -u https://spa.local --roe roe.yaml --accounts accounts.yaml --browser
# Resume after an interruption
heretic resume --engagement run.db --report findings.html
# CI gate โ fail the build on any HIGH+ finding, emit SARIF
heretic scan -u https://staging.local --roe roe.yaml --accounts accounts.yaml \
--classes bola,bfla,excessive_data_exposure --sarif heretic.sarif --fail-on high
๐ค Choosing an AI model
HERETIC talks to any OpenAI-compatible endpoint over plain HTTP (no vendor SDK). It auto-detects the best model available โ a hosted key or a local Ollama model โ so you usually don't pass --model at all.
--model id |
Backend | Key env var | Notes |
|---|---|---|---|
nemotron-super |
NVIDIA (free API) | NVIDIA_API_KEY |
Recommended default brain |
nemotron-nano |
NVIDIA (free API) | NVIDIA_API_KEY |
Cheap workhorse |
gemini-flash |
Google Gemini | GEMINI_API_KEY |
1M context (pip install -e ".[gemini]") |
groq |
Groq (Llama 3.3 70B) | GROQ_API_KEY |
Fast |
openrouter-r1 |
OpenRouter (DeepSeek-R1 free) | OPENROUTER_API_KEY |
Diverse 2nd opinion for the refuter panel |
ollama:<model> |
Local Ollama | (none) | Fully private โ nothing leaves the box |
auto |
Per-phase routing | โ | Big model for intent/judge, small for the rest |
fake |
Scripted (offline) | (none) | No LLM โ deterministic classes only |
Set a key (any one is enough) via env var or a .env file in the working directory:
# .env (auto-loaded, gitignored โ never commit keys)
NVIDIA_API_KEY=nvapi-xxxxxxxx
Go fully offline / private with a local model:
ollama pull qwen2.5:7b # or any model; HERETIC auto-selects the largest local one
heretic scan ... # --model omitted โ uses your local model, no data leaves the host
Check what's wired up before a run:
heretic doctor -u https://target.local
โ๏ธ Configuration
You need two files. Generate starters with heretic init, then edit.
1. roe.yaml โ Rules of Engagement (the authorization gate)
HERETIC refuses to run without a valid, signed RoE. This is a hard security boundary โ the LLM cannot override it.
engagement: "my lab engagement" # free-text label
authorized_by: "you@example.com" # REQUIRED โ who authorized this test
signed: true # REQUIRED โ must be true or it refuses to run
scope:
allow: # every request target MUST match one of these
- "*.target.local"
- "127.0.0.1"
- "10.0.0.0/8" # CIDR ranges supported
exclude: # never touch these, even if in allow
- "*/admin/delete*"
mode: dry-run # dry-run (read-only) | live (allows state changes)
max_rate_rps: 5 # request rate cap โ don't DoS the target
max_parallel: 3 # concurrency cap for race-condition tests
destructive_allowed: [] # e.g. ["price_tamper"] or ["*"] to fire state-changing tests
classes: [bola, bfla, excessive_data_exposure] # omit for all classes
# Optional: a header sent on EVERY request (e.g. bug-bounty program attribution)
# headers:
# X-Bug-Bounty: "your-handle"
# Objects to harvest ids from + test for BOLA (omit entirely to auto-discover):
objects:
- name: order
list_url: "/api/orders" # each role fetches its OWN orders (harvest ids)
item_url: "/api/orders/{id}" # non-owners are tested against this (cross-role BOLA)
id_field: "id" # the id key inside each list item
# list_path: "data" # dotted path to the array, if nested
Advanced RoE blocks โ login_objects, races, per-phase models
# When the owned id comes from the LOGIN response, not a list endpoint
# (e.g. Juice Shop hands you your basket id at login):
login_objects:
- name: basket
item_url: "/rest/basket/{id}"
id_from: "authentication.bid" # dotted path in the login JSON
# Race / TOCTOU probes โ fire N identical requests, confirm no more than
# `expect_max_success` succeed (e.g. a single-use coupon applied twice):
races:
- name: coupon_double_apply
url: "/api/coupon/apply"
method: POST
body: { code: "SAVE10" }
as_role: userA
parallel: 10
expect_max_success: 1
# Coupon abuse โ redeem a single-use code repeatedly IN SERIES (not concurrent;
# that's `races:`). Confirmed if the server accepts it more than `max_uses` times:
coupons:
- name: welcome10
url: "/api/coupon/apply"
code: "WELCOME10"
code_field: "code" # body field carrying the code
as_role: userA
max_uses: 1 # single-use
success_field: "applied" # optional: dotted field marking a redemption
# Per-phase model routing (only used with `--model auto`):
models:
intent: nemotron-super
hypothesis: ollama:nemotron-nano
judge: nemotron-super
refute: openrouter-r1
2. accounts.yaml โ test identities (operator-owned only)
HERETIC uses multiple roles at once for differential (cross-session) testing โ that's how it proves BOLA.
login:
url: "/api/auth/login"
method: "POST"
token_field: "token" # json field ยท dotted "data.token" ยท or "cookie:session"
auth_header: "Authorization: Bearer {token}"
roles:
- { name: guest, creds: null } # unauth baseline
- { name: userA, creds: { email: "userA@test.local", password: "Pass123!" } }
- { name: userB, creds: { email: "userB@test.local", password: "Pass123!" } } # the "victim" for BOLA
- { name: admin, creds: { email: "admin@test.local", password: "Admin123!" } }
๐
heretic connectauto-detects all of this โ including session-cookie logins (Django / Rails / PHP / Express โtoken_field: "cookie:NAME"), CSRF-guarded logins (Laravel / Angular / Rails โ it pre-fetches and replays the token via acsrf:block), and form-encoded logins (content_type: "form"). You rarely write this file by hand.
๐ OTP / MFA / SSO? You can't script those logins โ so paste a token instead. Give the role a
token:field with a bearer token grabbed from your browser, and HERETIC skips login for that identity:- { name: userA, token: "eyJhbGciOi..." }
Manual accounts.yaml for a cookie + CSRF login (if you'd rather not use connect)
login:
url: "/api/login"
method: "POST"
content_type: "form" # or "json"
token_field: "cookie:session" # auth lives in a Set-Cookie, not a JSON token
auth_header: "Cookie: session={token}"
csrf: # pre-fetch a CSRF token and replay it on login
fetch_url: "/login" # GET this first (seeds the token)
source: "cookie:XSRF-TOKEN" # cookie:NAME | meta:NAME | input:NAME | json:dotted
header: "X-XSRF-TOKEN" # send the token in this header โฆ
# field: "_csrf" # โฆ and/or this body field
roles:
- { name: guest, creds: null }
- { name: userA, creds: { username: "userA", password: "Pass123!" } }
- { name: userB, creds: { username: "userB", password: "Pass123!" } }
โ ๏ธ
accounts.yamlholds credentials โ it's gitignored by default. Never commit it, never use real end-user data.
๐ฏ What it finds
| Class | --classes id |
What it catches | Oracle | Changes state? |
|---|---|---|---|---|
| BOLA / IDOR | bola |
One user reading another's object | Cross-session differential | No โ |
| Broken function-level auth | bfla |
Admin function reachable by a lower role | Function-level access diff | No โ |
| Excessive data exposure | excessive_data_exposure |
A list leaking other users' / secret data | Owner co-mingling | No โ |
| Price tampering | price_tamper |
Server trusting a client-supplied price/qty | Invariant assertion | Yes โ ๏ธ |
| Mass assignment | mass_assignment |
Registration accepting a privileged field | Reflected-field assertion | Yes โ ๏ธ |
| Workflow bypass | workflow_bypass |
Finalizing without a prerequisite step | State-delta judge (+ refuter panel) | Yes โ ๏ธ |
| Race / TOCTOU | race_condition |
Non-atomic check-then-act (double-spend) | Parallel-fire success count | Yes โ ๏ธ |
| Coupon abuse | coupon_abuse |
Redeeming a single-use coupon past its limit | Sequential-redemption count | Yes โ ๏ธ |
| Auth-flow abuse | auth_flow |
Reset-token binding / skipping a verification step | Invariant assertion / state-delta judge | Yes โ ๏ธ |
โ
read-only classes are safe to run against production โ no LLM key required, no state changed.
โ ๏ธ state-changing classes are gated: they only fire in --mode live and when listed in the RoE's destructive_allowed. In dry-run they're skipped and the tool tells you why.
coupon_abuseruns deterministically from acoupons:RoE block (see below);auth_flowis LLM-driven (needs a model). The rest of the state-changing set is fully mechanical.
๐ง How it works
The LLM proposes; deterministic code enforces and confirms. That split is the whole design โ an LLM is great at guessing where a logic bug might be, and terrible at being trusted that one happened.
flowchart LR
A[1. Recon<br/>multi-role login<br/>+ id harvest] --> B[1b. Discovery<br/>OpenAPI ยท JS ยท browser<br/>ยท wordlist ยท listโdetail]
B --> C[2. Intent model<br/>LLM extracts<br/>business invariants]
C --> D[3. Hypotheses<br/>invariant-violation<br/>tests + knowledge]
D --> E[4. Execute<br/>scope-gated,<br/>rate-limited]
E --> F[5. ORACLE<br/>prove it or drop it<br/>= the moat]
F --> G[6. Chain<br/>compose primitives<br/>into higher impact]
G --> H[Report<br/>table ยท html ยท json ยท SARIF]
- Recon logs in as every role and harvests the ids each one owns.
- Discovery finds the attack surface itself โ parses OpenAPI/Swagger, extracts API routes from SPA JS bundles, optionally drives a headless browser to capture runtime XHRs, and follows list endpoints to real item endpoints (
/thing/{id}) โ so you don't hand-writeobjects:. - Intent model (LLM) reads the observed API and writes down the business rules it should enforce.
- Hypotheses turn each invariant into a concrete test. Invented endpoints are detected and regenerated against the real surface (anti-hallucination).
- Oracle is the moat: a business-logic bug throws no error and returns
200 OK, so the Oracle proves an invariant was violated โ deterministically where possible, and with an adversarial 3-skeptic refuter panel for the LLM-judged classes. An LLM can never veto a deterministic proof. - Chain composes confirmed primitives (e.g. two BOLA reads โ bulk exfiltration).
Full detail: docs/01-ARCHITECTURE.md ยท docs/03-ORACLE.md ยท docs/02-WORKFLOWS.md.
๐ค Output & reporting
| Format | How | Use |
|---|---|---|
| Terminal table | (default) | Live view while it runs |
| JSON | -o json |
Pipe into other tools |
| Markdown | -o md |
Paste into a report / ticket |
| HTML | --report findings.html |
Shareable, self-contained report |
| SARIF 2.1.0 | --sarif out.sarif |
GitHub / GitLab / Azure code scanning |
Every finding carries a proof bundle: the oracle used, the evidence (status codes, body similarity, distinct owners, โฆ), a reproducible PoC request sequence, a confidence score, and a remediation.
๐ Run it in CI
Because every finding is Oracle-proven (~0 FP), a failing build is a real bug, not AI noise โ the property that makes a security gate developers keep switched on.
# .github/workflows/heretic.yml
- uses: SYCO7/heretic@v1.0.0
with:
url: https://staging.example.com
roe: roe.yaml
accounts: accounts.yaml
classes: bola,bfla,excessive_data_exposure # read-only set โ safe on every PR, no LLM key
fail-on: high
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: heretic.sarif }
The read-only classes need no LLM key and never change state, so they're safe on every PR. Run the state-changing classes on a schedule against staging. See docs/CI.md.
๐ก๏ธ Safety & legal
HERETIC is built for authorized testing only and enforces it in code:
- Authorization gate โ refuses to run without a signed RoE naming who authorized the test.
- Scope allowlist โ every request is checked against
scope.allow(host globs + CIDR) before it leaves the process; anything out of scope or matchingexcludeis hard-blocked. The LLM cannot bypass this. - Read-only by default โ
dry-runmode does no state changes. State-changing classes fire only inlivemode and when explicitly listed indestructive_allowed. - Rate limited โ
max_rate_rps/max_parallelthrottle every identity so you don't stress the target.
Only test systems you own or are explicitly authorized to assess. See docs/07-GUARDRAILS.md.
โ FAQ
Do I need an API key?
No. The deterministic classes (BOLA, BFLA, excessive-data-exposure) run with no LLM at all. A key (or a local Ollama model) unlocks the reasoning-driven classes (price/workflow/mass-assignment). heretic bench self-tests with zero keys.
Will it break my app or delete data?
In the default dry-run mode, no โ it's read-only. State-changing tests are double-gated behind --mode live and the RoE's destructive_allowed list, and even then are scoped to your test accounts and rate-limited.
It found nothing / login failed.
Run heretic doctor -u <url> to check reachability and keys. If login failed, confirm the credentials in accounts.yaml and that the login endpoint/token field auto-detected correctly โ or set them explicitly. For OTP/MFA/SSO, paste a bearer token: on the role instead of creds:.
The AI backend errored or got rate-limited โ did I lose my scan?
No. The LLM layer retries with backoff on rate-limits / 5xx / transient errors, and if a backend is still down, the run degrades gracefully: the deterministic classes (BOLA / BFLA / data-exposure and the mechanical state-changing checks) already completed and are kept, and you get a clear LLM phase skipped โ โฆ message instead of a crash. Run heretic doctor --ping first to confirm your key actually works, or switch to a local Ollama model.
How do I keep everything private / offline?
Use a local model: ollama pull qwen2.5:7b, then run without --model. Nothing leaves the host โ the LLM calls go to localhost.
How do I prove it actually works?
heretic bench (offline: 126 tests, precision/recall 100%, FP 0%) and heretic livecheck --profile targets/<name> -u <url> (live, scored against ground truth on crAPI, OWASP Juice Shop, and VAmPI โ 0 false positives each). Full breakdown in Validation; reproduction in docs/09-LIVE-VALIDATION.md.
๐ Full documentation
| # | Doc | What |
|---|---|---|
| 0 | docs/00-VISION.md |
Problem, thesis, the moat |
| 1 | docs/01-ARCHITECTURE.md |
Components, data flow, tech stack |
| 2 | docs/02-WORKFLOWS.md |
Phase workflow + flowcharts |
| 3 | docs/03-ORACLE.md |
The hard part โ verification / FP kill |
| 4 | docs/04-LLM-BACKENDS.md |
Model analysis + free AI options |
| 6 | docs/06-USAGE.md |
Deeper usage guide |
| 7 | docs/07-GUARDRAILS.md |
Scope, safety, legal |
| 9 | docs/09-LIVE-VALIDATION.md |
Reproduce the live runs, score recall/FP |
| 11 | docs/11-REAL-WORLD.md |
Run on an authorized real target โ get the real-world number |
| โ | docs/CI.md |
Run in CI โ SARIF + GitHub Action |
๐ค Contributing & license
Issues and PRs welcome. Run the suite before pushing:
make test # pytest
make bench # offline FP-gate
make lint # ruff
License: Apache-2.0. Lab-first โ authorized testing only.
Built by SYCO7
If HERETIC finds you a bug, โญ the repo.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file heretic_agent-1.0.0.tar.gz.
File metadata
- Download URL: heretic_agent-1.0.0.tar.gz
- Upload date:
- Size: 200.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eeff9ea4d8a4b690cf65b4462c2cb8c657db8cb563f9b24e4b996e3eaff886ad
|
|
| MD5 |
713cf258be432e19fcb2cfce3a9a5672
|
|
| BLAKE2b-256 |
349460622e1da48297d5489050ebac3603f1142b543ff7b3853b89c106cf2245
|
File details
Details for the file heretic_agent-1.0.0-py3-none-any.whl.
File metadata
- Download URL: heretic_agent-1.0.0-py3-none-any.whl
- Upload date:
- Size: 120.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c5ec4dcef8a9fb7d81cabb432357e145bd2664b0f0a3dedf88f1e37b8495ebf
|
|
| MD5 |
b1a737ba9e67cf4011145224c633e706
|
|
| BLAKE2b-256 |
7960f66358f350147bf5f9ae337bd8b024c53ced7eb1ed5d0b3414569767f30e
|