Proof,
not guesses.
Follow the data.
Proof is the only security signal that survives every re-run. Regex scanners guess from patterns; LLM reviewers guess from context, charge per PR and send your code out. heisen-slop follows each request value through your code with deterministic dataflow analysis, and when it can't prove a path it abstains and says so — instead of a generative guess. A block is a proven path from attacker input to a dangerous sink — never a pattern that happened to match.
A dataflow engine, not a pattern scanner.
The engine reads your code the way an interpreter would: it tracks every value from where it enters — a request parameter, a form field, a CLI argument — to where it lands: a shell, a query, a template, a deserializer. It raises a finding only when it can prove the path, and clears code only when it can prove the value is a constant. Anything it cannot prove, it abstains on — no block, no false green.
29 classes across 6 languages — 127 detectors.
Each ✓ is a live dataflow detector that follows request input to a dangerous sink in that language. This is the deep-scan layer of the Firewall; the Firewall's 125-class catalog also includes pattern-level gates the GitHub Action runs on your runner.
✓ = a live detector for that language. — = not covered in that language today. The hosted deep scan leaves trust-boundary out: on real applications it was mostly noise.
It knows your framework, your database and your HTTP client.
A taint engine is only as good as the sources and sinks it knows. These are modelled today — anything else is followed as ordinary code, and an unknown call makes the engine abstain rather than guess.
One engine, reached through the tools you already run.
GitHub only for now: GitLab and Bitbucket are not supported by the Firewall.
Prove → abstain → decide. Nothing is ever guessed.
Deterministic taint analysis
The engine interprets each file abstractly and tracks taint from every source to every sink. A proven path is a BLOCK (p = 0.94); a value proven constant is CLEAN (p = 0.02). $0, auditable, and identical on every run.
Abstains on the ambiguous band
When a dangerous sink meets a request source but no path can be proven, the engine abstains: it returns no verdict for that case. It never turns the case into a block, and it never counts it as clean.
A verdict you can audit
The evidence carries the sink and the flow — never your source code. On SlopGrade Firewall the deep scan is opt-in on private repos and advisory by default; blocking on its findings is a separate switch. Only Python can return a proven CLEAN today; the other languages block or abstain.
The axis the incumbents can't follow.
vs. regex scanners
A regex fires on text that looks dangerous. The engine fires on data that provably flows to a sink — so a safe parameterized query with the same keywords stays clean.
vs. LLM reviewers
An LLM can answer differently on re-run, costs money per PR, and sends your code to a third party. A proven path here is deterministic and makes no model call. When no path can be proven, the engine abstains instead of guessing, and the hosted deep scan never stores a line of your code.
vs. cloud SaaS
Cloud-hosted scanners copy your repo out. On a private repo the default Firewall run sends only a structural fingerprint. The deep scan is analysed in memory and dropped. Running the engine in your infrastructure can be set up under an Enterprise agreement, on request.
Every number here comes from a run — including the weak ones.
Read the first number with the last one: the engine is precise when it decides, and it often abstains. On real CVE code (GitHub advisories, held-out split), blocks are right at least 3 times in 4 (25 of 32, a floor: every block on the fixed file counts as wrong); on 52,089 ordinary open-source pull requests it blocked 245, 46 of them for a real flaw — that is why the deep scan is advisory by default and blocking is a separate opt-in. The CI gate's library rule pack is graded the same way: a whole-repo review of 240 of its MEDIUM lines found about 1 in 4 true (25.0 %, 18.0–32.9), not the 32.5 % that snippet labels gave. Only the disagreements got a second reading and nothing was executed, so the pack stays advisory and never blocks.
What we are building next.
Straight answers.
Does it follow data across files?
Yes in Python (imports, 3 levels), JavaScript/TypeScript (relative imports), Ruby (require_relative) and Go (the package). Not yet for TypeScript path aliases or Java calls into another class.
Does my code leave my infrastructure?
Not by default: the Firewall run sends a structural fingerprint — file paths, {file, line, kind} and the table and column names the cross-tenant check needs, never file contents. The deep scan is opt-in on private repos (paid) and on by default on public repos (heisen-slop) — it sends at most 80 files that a local detector flagged or that hold a dangerous call to the engine, which analyses them in memory and drops them. When no path can be proven, the engine abstains.
How is this different from Snyk, Semgrep or CodeQL?
Semgrep and Snyk Code lead with pattern rules; CodeQL does dataflow but needs query authoring and ships no tenant-isolation gate. The engine blocks only a proven path and abstains when it cannot prove one. The trade-off is recall: on Semgrep's own rule tests, Semgrep finds more.
Do you support GitLab or Bitbucket?
Not for the Firewall yet — it is GitHub only (Action, checks, OIDC).
Put proof in your pipeline.
Add the deep scan (heisen-slop) to your pull requests — free on public repos, opt-in on private repos, deterministic, advisory by default.
Regulated or air-gapped? Talk to us about running the engine in your infrastructure →