Gadriel vs. Semgrep: The Whole Security Job vs. the Best Free SAST Engine
Six deliberately-vulnerable goat apps, five languages, first-time scans. An honest head-to-head between a great open-source SAST engine and a single-pass security platform.
COMPARISON · SEMGREP·2026-07-10·12 MIN READ
CISO NOTE
CISO note — the Gadriel differentiator. Semgrep is a superb SAST engine. Gadriel is a security platform in one local command: SAST + SCA (live OSV feed) + secrets + container + IaC/config + API + AI/LLM controls in a single deterministic pass. 100% local, no code egress, works air-gapped, emits SBOM (SPDX + CycloneDX) and a 10-framework compliance report — with an optional bring-your-own-LLM verification pass on top. If your board asks "what covers the whole code side of AI-assisted development in one gate?" — that is the box Gadriel is built for.
Let's be straight up front: Semgrep is an excellent, popular, free, open-source SAST engine. Its community rule library is broad, its custom-rule system is best-in-class, it runs locally, and on several of these apps it flagged more raw source-code patterns than Gadriel did — notably Java and JavaScript injection variety, and cross-site-scripting. Where Semgrep's core mission is source code, it does that one thing very well, and we're not going to spin otherwise.
Gadriel is a genuine peer on its strong languages (Python, Go) and tighter on false positives — and it does the whole job in one pass. On the same repositories, in a single fast, local, offline-capable run, Gadriel scans your code (SAST) and your libraries (SCA) and secrets and containers and configuration and APIs and AI/LLM-specific risks, and emits compliance reports and an SBOM — with an optional AI pass that can re-verify findings on top. Semgrep's free core does the first of those; matching the rest means buying and wiring together several separate products. If Semgrep is a superb engine for scanning code, Gadriel is a complete security platform that happens to include one.
The comparison below rests on Gadriel's default scan: one local command that sweeps your whole stack in a single deterministic pass. That pass runs SAST (taint/AST flow), SCA (dependency CVEs via OSV), secrets, container/IaC, config/AI-runtime, and API/OpenAPI analysis together, tags every finding with a confidence tier, and fuses the results into verified findings plus an SBOM, 10-framework compliance mapping, and a static HTML report.
Gadriel also ships an optional AI pass (Tier-2, --tier2 / GADRIEL_TIER2 / [tier2].enabled, off by default) that does two distinct jobs. It verifies — adversarially re-checks Tier-1's gating SAST findings to refute or confirm them (this round: 19/19 confirmed, 0 refuted). And it hunts — semantically reads the source for the vuln classes deterministic taint rules structurally miss (IDOR, missing/broken authz, forgeable-token auth), surfacing them as advisory findings for review (this round: +25 own-code issues Tier-1 alone did not reach). Its differentiator is bring-your-own-LLM: it borrows the model the host agent is already running — Claude in Claude Code, GPT in Cursor, or a local Ollama model — so Gadriel makes no API call of its own: no vendor model to buy, no code egress, no second bill, works air-gapped. It is a bonus box, not the basis of the per-repo comparison below, and its adds are advisory (flagged for review), not build-gating. Semgrep's free core is a strong implementation of the SAST box in the default pass; it has no equivalent of the SCA/secrets/container/config/API rows.
flowchart LR
R[Source repo] --> T1
subgraph T1[Default scan — deterministic, one local pass]
direction TB
S1[SAST taint/AST]:::c --- S2[SCA + OSV CVE]:::c --- S3[Secrets]:::c
S4[Container / IaC]:::c --- S5[Config / AI-runtime]:::c --- S6[API / OpenAPI]:::c
end
T1 --> F[Findings + confidence tiers]
F --> OUT[Verified findings + SBOM SPDX/CycloneDX<br/>+ 10-framework compliance + static HTML report]
F -.-> T2[Tier-2 optional — host-LLM verification<br/>off by default]
T2 -.-> OUT
classDef c fill:#eef,stroke:#88a;
DIAGRAM
NOTE
Methodology. Every scan below is a first-time run — no tuning, no allow-lists, no cherry-picked rulesets. Same machine, same day, same repos. What you see is what a new user would see on their first gadriel scan and their first semgrep --config auto.
Every scan was a first-time run on a repository Gadriel was never trained or tuned on, all measured on the same machine in July 2026. Tools: Gadriel 1.2.1 and Semgrep 1.169.0 (OSS, --config auto).
Repo
Language / stack
Why it's here
pygoat
Python / Django
The original battery — RCE, pickle, yaml, command-injection, SQLi
Gadriel figures are from the July 2026 live re-run (Gadriel 1.2.1, offline). Semgrep figures are from the same test round. Gadriel's counts are its whole-job total across SAST, SCA, secrets, container, and config; Semgrep's are source-code findings only.
Repo
Gadriel time
Gadriel findings
Semgrep findings
Honest read
pygoat (Python)
3.7s
38
found the RCE/injection bugs
Peers on the dangerous bugs; Gadriel's strongest repo (18 SAST hits) plus SCA/secrets/container
django.nV (Python)
14.4s
12
50
Peer on SQLi + secret + Django-1.8.3 SCA; Semgrep wider on IDOR/CSRF/XSS
vulpy (Python)
2.5s
5
45 (18 in good/)
Gadriel win on precision: full SQLi recall, no false positives on the hardened tree
govwa (Go)
3.0s
11
44
Peer on SQLi (now firing via Gadriel's Go formatted-SQL-injection detector); Semgrep leads on Go XSS
dvja (Java)
5.3s
15
5
Semgrep caught 2 SQLi to Gadriel's 1; Gadriel found the Struts2 RCE deps + 10 container issues
NodeGoat (JS)
5.2s
14
35
Semgrep wider on JS SAST; Gadriel caught the marquee eval + committed private key + deps
Gadriel's counts are default-scan totals. Semgrep's totals include its own noise (see vulpy's 18 findings inside already-fixed code).
The scoreboard above counts Gadriel's whole-job output. Narrowing to SAST alone — the box Semgrep is built for — here is the default-scan source-code comparison:
Repo
Gadriel SAST
Semgrep
Gadriel Tier-2 (optional, verified)
Read
pygoat
18
peer on the dangerous bugs
6/6 confirmed
Gadriel's strongest repo; both catch the RCE/injection bugs
django.nV
7
50
5/5 confirmed
Peer on SQLi + cmd-inj; Semgrep wider on IDOR/CSRF/XSS
vulpy
4
45 (18 in good/)
2/2 confirmed
Full recall on bad/, zero findings in the hardened good/ tree
govwa
3
44
3/3 confirmed
Peer on SQLi ; Semgrep leads on Go XSS
dvja
1
5 (2 SQLi)
1/1 confirmed
Semgrep's Java data-flow is deeper here
NodeGoat
4
35
2/2 confirmed
Semgrep wider on JS SAST; Gadriel lands the marquee eval
Total
37
—
19/19 confirmed
Semgrep leads on raw SAST breadth; Gadriel is a peer on Python/Go injection
The Gadriel Tier-2 column is the optional AI self-verification pass (--tier2, off by default) run over the gating-eligible Medium-confidence findings — it is a bonus feature, not the basis of this comparison.
Optional: Gadriel Tier-2 (verify + hunt). Tier-2 is Gadriel's optional AI pass, enabled with --tier2 (or GADRIEL_TIER2 / [tier2].enabled) and off by default. Its distinguishing property is bring-your-own-LLM: it borrows the host agent's already-running model — Claude in Claude Code, GPT in Cursor, or a local Ollama model — so Gadriel makes no API call of its own (no vendor model to buy, no code egress, no second bill, works air-gapped with a local model). It runs two passes. Verify: all 19/19 gating-eligible Medium-confidence SAST findings across the six repos were re-checked through Gadriel's real fusion engine and every one was confirmed, none refuted. Hunt: it then reads the source for the access-control family the taint engine can't reach (IDOR, missing/broken authz, forgeable-token auth) and surfaced +25 additional own-code issues as advisory, non-gating findings. The table below tallies both against the deterministic Tier-1 baseline:
Repo
Tier-1 gating SAST
+ Tier-2 verify (confirmed)
+ Tier-2 hunt (advisory adds)
Own-code total w/ Tier-2
pygoat
18
6/6 ✓
+4
22
django.nV
7
5/5 ✓
+4
11
vulpy
4
2/2 ✓
+4
8
govwa
3
3/3 ✓
+4
7
dvja
1
1/1 ✓
+4
5
NodeGoat
4
2/2 ✓
+5
9
Total
37
19/19 confirmed, 0 refuted
+25
62
The hunt adds are all classes rule-based taint analysis structurally misses — IDOR/broken-object-authz (CWE-639), missing function-level authz (CWE-862), missing authentication (CWE-306), forgeable/unsigned-token auth (CWE-287/345/565/640), plus injection/traversal on the SAST-thin Java repo. They are surfaced and flagged for review, never used to gate a build. It's a bonus feature — explicitly not the basis of the per-repo comparison above.
Semgrep does one box in this grid extremely well. The rest of the rows are why matching Gadriel's coverage means Semgrep plus several other products you'd buy and wire together — and the Gadriel + Tier-2 column shows what the optional AI pass adds on top:
Capability
Gadriel (default)
Gadriel + Tier-2
Semgrep
SAST / own-code injection
✅
✅
✅ (strong — this is Semgrep's core)
SCA (deps/CVE)
✅
✅
❌ (paid tier only)
Secrets
✅
✅
partial
Container / IaC
✅
✅
❌
Config or AI-runtime
✅
✅
❌
API (OpenAPI)
✅
✅
❌
AI/LLM risk
✅
✅
❌
Access-control / IDOR / broken-authz
~ structural gap
✅ advisory (semantic hunt)
❌
Self-verification (AI pass)
— (optional)
✅ BYO-LLM (your Claude/GPT/local Ollama)
❌
Local / offline
✅
✅
✅
SBOM
✅
✅
❌
One command, one pass
✅
✅
❌
The honest reading: Semgrep matches Gadriel on the two rows that define its mission — local SAST and offline operation — and leads on raw rule breadth for several languages. Every other row is coverage Semgrep's free core doesn't ship, including the own-code access-control layer its rule engine can't reach and the optional self-verification pass it has no equivalent for. (Semgrep's own AI add-on, Semgrep Assistant, does exist, but it calls its own cloud model; Gadriel's Tier-2 instead borrows the LLM you're already running and stays local.)
A Django training app packed with RCE, pickle, unsafe yaml, command-injection, and SQL-injection bugs. Both tools found every one of the dangerous code bugs — clean peers here. This is Gadriel's strongest repo: its 38 findings include 18 SAST hits (many L3-critical), among them the pickle RCE (L1-072, insec_des/main.py:36), command injection (L3-017, mitre.py:233), SQL injection (L3-054, views.py:162), unsafe yaml/deserialization (L3-016/020/035), a hardcoded key (L4-115), and the SECRET-486 credential in settings.py:25 — alongside dependency, secret, and container findings. Bottom line: on the code, a tie; on coverage, Gadriel does the surrounding job Semgrep's free core doesn't touch.
nVisium's OWASP-Top-10 Django app on the end-of-life Django 1.8.3. Semgrep reported 50 findings to Gadriel's 12, and several of the extras are real own-code issues Gadriel does not yet flag: IDOR/access-control sinks, four @csrf_exempt handlers, and template | safe XSS. Both caught the SQL injection — Gadriel fires the critical CODE-W1-L3-014 (views.py:183, from Gadriel's Python formatted-SQL-injection detector) plus command injection L3-017 (misc.py:33, critical), an open-redirect L1-821 (views.py:387), the hardcoded SECRET_KEY (SECRET-486), and the known-vulnerable Django 1.8.3 (SCA-056) from requirements.txt — none of the last three of which the free Semgrep engine looks at. Every view here is unauthenticated, so the SQLi and command-injection both show a clean request.POST→sink taint path. Bottom line: Semgrep is the wider net on access-control/XSS breadth; Gadriel pairs the core injection catch with the leaked key and the vulnerable framework in one pass.
A Flask teaching app that ships the same features twice: an exploitable bad/ tree and a hardened good/ tree — a rare chance to measure precision, not just recall. Both tools caught the SQL-injection bugs — Gadriel's formatted-SQL fire, CODE-W1-L3-014 critical at bad/libuser.py:12, is the Python formatted-SQL fix, alongside debug=True (L4-115) and auth-over-HTTP (L4-145) — and all of Gadriel's findings land in bad/, none in good/. The difference is noise: Semgrep raised 45 findings, 18 of them inside the already-fixed good/ tree — many on correctly parameterized queries. Gadriel raised 5, firing only where a query is genuinely injectable — full recall on the exploitable bad/ sites and zero findings inside the hardened good/ tree. Bottom line: a clean Gadriel win on precision — full recall on the bugs, silence on the fixes.
The "Go Vulnerable Web Application" (Go / MySQL). On SQL injection the two are now peers — Gadriel's Go formatted-SQL-injection detector (CODE-W1-L2-002) fires live in this run, at function.go:41 (critical) and database.go:24 (high), tracing user input into an fmt.Sprintf-built query, and it also flags weak MD5 hashing (L1-313, user.go:160). Semgrep is genuinely ahead on Go XSS, flagging roughly a dozen template.HTML(userinput) unsafe-HTML spots that Gadriel's Go analysis is currently lighter on — we credit that plainly. Gadriel's 11 findings also span 4 container/Dockerfile issues, a CI-config finding, and 2 Go-module dependency findings. Bottom line: peer on SQLi, Semgrep leads on XSS, Gadriel covers the container/config/deps Semgrep's free core doesn't.
The "Damn Vulnerable Java App" (Spring / Struts2 / Maven). This is the honest low point for Gadriel's SAST: Semgrep caught two SQL-injection flaws to Gadriel's one — its Java data-flow rules are more mature than ours today. Gadriel's single SAST hit is the JPQL injection CODE-W1-L1-1004 at ProductService.java:48 (critical). But the most likely breach path here isn't the query, it's the libraries: dvja ships an RCE-grade Apache Struts 2.3.30 and a Log4Shell-era Log4j. Semgrep's free core reported zero vulnerable dependencies; Gadriel flagged the Struts2 CVEs (SCA-006/008: CVE-2018-11776, CVE-2020-17530) plus 10 container hardening issues in the same 5.3s run. Bottom line: Semgrep is the better pure Java source scanner here; Gadriel's edge is breadth — the dependency and container risk Semgrep's free engine never looks for.
OWASP's Express/MongoDB Top-10 app. On raw JS source recall, Semgrep leads — its 35 findings span NoSQL $where injection, SSRF, ReDoS, and plaintext credentials, categories Gadriel's JS engine misses today. Gadriel's SAST returned 4, but caught the marquee eval() code-injection (CODE-W1-L1-001, contributions.js:32, critical), a second eval sink at Gruntfile.js:165 (L1-008), an open-redirect (CODE-W1-L1-1696, index.js:72), and — being more than a code scanner — the committed TLS private key (SECRET-001, server.key) that Semgrep's free core doesn't report. Gadriel's 14 findings also include npm dependency and container coverage. Bottom line: Semgrep wins JS SAST breadth; Gadriel lands the highest-impact issues plus deps, secrets, and containers in one run.
KEY TAKEAWAY
Semgrep is the sharpest free SAST engine. Gadriel is a peer on the dangerous bugs — and it also brings SCA, secrets, containers, config, API, and AI/LLM checks in the same one-command pass. Different jobs, honestly measured.
Breadth in one tool. Semgrep's free core scans source only. Gadriel does SAST and SCA and secrets and container and config and API and AI/LLM risk in a single command — the coverage you'd otherwise assemble (and, for Semgrep's SCA and full secrets, pay for) from several products.
Local, private, offline. Gadriel runs entirely on your machine and completes fully offline. No account, no upload, no server — decisive for IP-sensitive and regulated teams.
Precision. On vulpy, Gadriel fired on every injectable query and stayed silent on the parameterized ? rewrites, while Semgrep put 18 findings inside the hardened tree — zero Gadriel findings in the "clean" folder to Semgrep's 18.
Per-codebase learning. Decisions are remembered per-codebase, and an optional AI verification pass (off by default) can dismiss false alarms — accuracy improves over time in a way a static ruleset cannot.
Audit-ready by default. SPDX + CycloneDX SBOMs, an executive summary, and mapping to 10 compliance frameworks (EU AI Act, NIST AI RMF, SOC 2, HIPAA, PCI-DSS, OWASP LLM Top 10, CMMC, ISO 42001, and a Cyber-Insurance readiness checklist) come out of every scan.
Java SAST recall (dvja). Gadriel caught 1 of the 2 SQL-injection flaws Semgrep found, and Java own-code depth trails our Python and Go coverage. On Java today, Gadriel's story is the dependency + container + one-tool coverage, not SAST breadth.
JavaScript SAST breadth (NodeGoat). Gadriel catches the eval, the committed key, and the open-redirect (CODE-W1-L1-1696, medium) but misses the NoSQL $where injection, SSRF, and ReDoS that Semgrep flags.
Python category breadth (django.nV). Strong on injection, secrets, and SCA, but not yet on the pervasive IDOR, the @csrf_exempt CSRF holes, mass-assignment, or template | safe XSS.
Go XSS (govwa). The template.HTML(userinput) reflected-XSS family is a Semgrep catch Gadriel doesn't yet make.
The optional Tier-2 pass already addresses part of this: its bring-your-own-LLM semantic hunt surfaces the IDOR / missing-authz / broken-auth family as advisory (review-flagged, non-gating) findings — this round it added +25 own-code issues Tier-1 alone missed. Those adds are advisory, not gating; the deterministic Java/JS SAST-breadth gap is still real and being improved.
These are Gadriel's tracked detection backlog — the next benchmark-driven fixes, exactly as the formatted-SQL-injection detectors (Go and Python) came out of the previous round.
This is a practice, not a slide. Earlier rounds surfaced real, credible recall gaps: Gadriel reported zero findings on govwa's Go formatted-SQL shape and on vulpy's Python "...".format(user) / "..." % user → cursor.execute shape, while Semgrep caught them. We traced the root cause (a cross-file, bare-parameter taint source the provenance engine couldn't reach), shipped a narrow, source-optional matcher heuristic that stays precise on parameterized queries — Gadriel's Go formatted-SQL-injection detector for Go, and its Python formatted-SQL-injection detector for Python — unit-tested both, and re-validated them live against govwa, vulpy, and django.nV in this run. All three now fire their formatted-SQL criticals. That is the loop: benchmark surfaces a gap, we record and ship the fix, the next run confirms it.
Semgrep leads raw SAST breadth. More source-code rules across more languages, the widest Java/JavaScript injection variety, and the strongest cross-language XSS coverage in this set. That lead is real and stays.
Gadriel Tier-1 is a peer on Python/Go injection — SQLi, OS-command, code/eval — and tighter on false positives (vulpy: full recall on bad/, zero findings in good/). But it is honestly weak in two places: (a) Java/JS SAST breadth (dvja bottoms at 1 SAST hit, NodeGoat at 4), and (b) the access-control family — IDOR, missing/broken authz, forgeable-token auth — which is structurally invisible to AST taint rules because the bug is a missing check, not a tainted data-flow to a sink. Semgrep OSS, also rule-based, does not reach that family either.
Optional Tier-2 (your own LLM) closes exactly those two gaps. Reading the source semantically, it surfaced +25 advisory IDOR/authz/broken-auth issues no rule-based scanner in this set reaches — standout being dvja, where Tier-1 alone found 1 SAST bug and Tier-2 recovered the critical PingAction command-injection plus a product-IDOR / forgeable-admin-cookie / forgeable-reset-token account-takeover chain.
Net, on OWN-CODE security coverage, Gadriel + Tier-2 is the most complete tool in this comparison — Tier-1's injection strength plus Tier-2's access-control reach, 62 own-code findings surfaced across the six repos.
Two honesty caveats hold that claim in place. This is own-code coverage, and coverage is surfaced-and-flagged, not enforced — Tier-2 adds are advisory, not build-gating. And it is own-code only: it says nothing about dependency/CVE breadth, where dedicated SCA tools lead. Against Semgrep specifically, "most complete on own code" means Tier-1's injection peer-status plus the access-control family Semgrep OSS's rule engine cannot see — not that Gadriel out-detects Semgrep on the raw SAST breadth Semgrep leads. The Tier-2 differentiator versus Semgrep's own AI add-on (Semgrep Assistant) is delivery — your own local/host model, no vendor cloud call, no egress, no extra bill — not superior raw detection.
If Semgrep is a superb engine for scanning code, Gadriel is a complete security platform that happens to include one.
Fair to Semgrep, because it earns it: it's one of the best open-source code scanners available — fast, local, free, with a huge community rule set and a best-in-class custom-rule system. On raw SAST rule breadth, and on Java/JavaScript injection variety and cross-language XSS, it leads here. If a focused, free code scanner is all you need and you'll add separate tools for dependencies, secrets, containers, and compliance, Semgrep is an excellent choice.
Gadriel's fit is different. On its strong languages (Python, Go) it matches Semgrep on the dangerous injection bugs and is tighter on false positives — then it does the whole job around the code: dependencies, secrets, containers, config, APIs, and AI/LLM risk, learned per-codebase, and delivered with an SBOM and 10-framework compliance mapping, entirely on your machine and offline. Injection detection is the sharpest edge of this comparison, but it's one of eight pillars Gadriel validates in every scan alongside compliance, safety, operational, FinOps, coherence, teamwork, and bias. In one line: Semgrep is the better free engine for scanning your code; Gadriel gives you comparable detection on its strong languages as part of a complete, precise, private, self-improving security platform.
Test details: Gadriel 1.2.1 and Semgrep 1.169.0 (OSS, --config auto). All six were first-time scans on repositories Gadriel was never trained or tuned on, measured on the same test machine in July 2026. Gadriel figures are from the July 2026 live re-run (offline). Semgrep figures are source-code findings from the same round. All findings were verified against the source.