-
-
Offline verifier: receipts, fingerprints, UNKNOWN, OpenVEX and SARIF all cross-check.
-
Offline explorer: REACHABLE and NOT_REACHABLE from the same captured Orbit run.
-
Selftest: real evidence passes, fake-green evidence fails.
-
GitLab MR receipt: REACHABLE finding with a concrete Orbit graph path.
-
GitLab MR receipt: exhaustive NOT_REACHABLE with frontier exhausted and zero API errors.
-
Judge Pack: the full replay path and evidence contract for reviewers.
-
Judge Proof overview: verdicts generated from receipts, not marketing copy.
Inspiration
Security scanners are good at answering one question: does vulnerable code exist?
But in a merge request, reviewers need the next question answered:
Can this vulnerable code actually be reached from the application's entry points?
Without reachability context, scanner output becomes a flat list of alarms. A severe finding with no path from the attack surface gets mixed with reachable vulnerabilities that deserve attention now. Datadog's State of DevSecOps 2025 found that just 18% of critical-CVSS vulnerabilities are still considered critical after applying contextual prioritization. Four out of five "critical" findings get downgraded once context is applied, but separating signal from noise is still manual triage work.
I built ReachGate to turn vulnerability triage from scanner noise into verifiable GitLab evidence.
What it does
ReachGate uses GitLab Orbit as a code evidence graph for vulnerability reachability.
For each finding, ReachGate starts from the declared attack surface in reachgate.yml, walks Orbit's graph of files, definitions, imports and calls, and checks whether a graph path reaches the vulnerable definition.
This is graph reachability — a concrete import/call path from the attack surface to the vulnerable definition — not full data-flow taint. That boundary is deliberate, and it is never hidden: every certificate names the search strategy behind the verdict.
It returns three verdicts:
REACHABLE: a concrete graph path exists from a declared entry point to the vulnerable code.NOT_REACHABLE: the search exhausted its frontier within configured bounds, with no bound hit and zero API errors.UNKNOWN: the evidence is incomplete, so ReachGate refuses to pretend the finding is safe.
In the MR workflow, each verdict becomes a GitLab-native receipt comment with the graph path, rule breakdown, stable fingerprint and reachability certificate. CI also uploads a machine-readable reachgate-receipts.json artifact. The bundled MR workflow is advisory and comment-only by default, but the receipts and JSON artifacts are gate-ready evidence teams can wire into policy.
The core rule is simple: the LLM never decides the verdict. The agent can run the workflow and explain the result, but the decision comes from deterministic rules and Orbit graph evidence.
How I built it
ReachGate has four connected layers:
Orbit reachability engine
A Python engine queries GitLab Orbit and reconstructs reachability with bounded BFS overneighbors. It records why each walk stopped, so a cut-off search cannot be mistaken for proof.Deterministic policy and certificates
Fixed rule weights produceREACHABLE,NOT_REACHABLEorUNKNOWN. Every receipt includes a certificate with policy version, search bounds, evidence mode, API errors, frontier status and a stable fingerprint.GitLab MR workflow
CI posts fingerprint-idempotent receipts on merge requests and uploadsreachgate-receipts.json, giving reviewers and automation the same evidence without duplicate comment spam. Each receipt also renders the graph path as a Mermaid diagram that GitLab draws inline in the comment: a reachable finding shows the connected entry-to-vulnerability path, a not-reachable one shows the nodes with no path between them — so reviewers read the evidence, not just a label.Replayable evidence layer
The repo includes 422 focused tests, plus 5 standalone install-gate tests deselected by default; an offline proof verifier; OpenVEX and SARIF 2.1.0 exports; a sha256 evidence manifest; a machine-checkable Evidence Contract; an adversarialreachgate selftestthat rejects fake-green evidence; fix-verification over before/after receipts; a contract-check gate; an offline evidence explorer; a doctor command that checks whether declared entrypoint globs actually match indexed Orbit files; a coverage report that surfaces verdict counts, UNKNOWN reasons and blind spots; and a portable evidence capsule (reachgate capsule build) — a deterministic, byte-stable zip of the receipts, the OpenVEX and SARIF exports, the sha256 manifest, the offline verifier and a HOW_TO_VERIFY.txt — that a reviewer can carry away and verify offline with no token and no network, optionally Ed25519-signed (reachgate capsule sign,[sign]extra) for authenticity and tamper-evidence checkable with the public key alone.
ReachGate also runs through a /reachgate Agent Skill with GitLab Duo and Orbit MCP. The agent executes the same deterministic workflow; it does not invent verdicts.
What makes it different
Most AI security demos summarize scanner output. ReachGate does something stricter: it asks GitLab Orbit for graph evidence.
If a path exists, ReachGate shows it.
If no path exists and the search was exhaustive within configured bounds, ReachGate says NOT_REACHABLE.
If the graph, config, API or search bounds cannot support that conclusion, ReachGate says UNKNOWN.
That third verdict is a core feature. In security automation, an honest "not enough evidence" is safer than a confident false "not reachable."
ReachGate is not just another scanner. It is a portable evidence layer: the same receipt can be inspected by a human, verified offline, checked against an Evidence Contract, compared across runs, and exported to downstream security formats.
Challenges
The hardest part was making NOT_REACHABLE honest.
A bounded graph search can easily lie if a timeout, API error, missing definition, bad entrypoint glob or search cap is treated as "no path found." ReachGate only returns NOT_REACHABLE after an exhaustive negative: frontier exhausted, no bound hit, zero API errors. Anything less becomes UNKNOWN with the exact reason.
Orbit traversal also required real engineering work. Orbit does not provide native pathfinding, so ReachGate reconstructs paths with bounded BFS. I also found that some JavaScript imports appear as ImportedSymbol nodes instead of ordinary graph edges, so the engine treats matching imported symbols as first-class reachability evidence.
The other challenge was resisting overclaiming. A security tool should not say "safe" just because the graph is incomplete. That is why ReachGate has an Evidence Contract and fake-green fixtures: if a receipt claims NOT_REACHABLE while the search timed out, the contract check fails.
Accomplishments
I proved the workflow live on GitLab:
- MR !2 shows both outcomes from the same Orbit-backed pipeline: a
REACHABLESSRF receipt (score 85, 1 hop fromcontent/frontend/404/archives_redirect.js) with a concrete graph path, and an exhaustiveNOT_REACHABLEpath-traversal receipt. - MR !3 proves fingerprint-idempotent reruns: same findings, same fingerprints, no duplicate MR comments.
- Each MR receipt renders the graph path as an inline Mermaid diagram, so the reachable path — or its absence — is visible directly in the comment.
- A captured
UNKNOWNreceipt proves incomplete evidence does not become fake-green. reachgate selftestaccepts real evidence, rejects fake-green evidence, and keepsUNKNOWNas an evidence gap.reachgate verifyreplays the captured proof offline with no token and no network.- ReachGate exports the same receipt evidence to OpenVEX, SARIF 2.1.0, and a sha256 evidence manifest.
reachgate capsule buildpackages the same evidence into a deterministic, byte-stable capsule a judge can verify offline;reachgate capsule signadds an optional Ed25519 signature, so authenticity and single-byte tampering are checkable with the public key alone.- The Evidence Contract and
contract-checkmake overclaiming machine-checkable. - Fix verification can compare before/after receipt artifacts and only claim
reachability_removedwhen the after receipt is an exhaustiveNOT_REACHABLEunder the same policy. - The offline explorer and Judge Pack make the proof easy to inspect during review.
- Everything ships as one
reachgateCLI —verify,coverage,export-vex/export-sarif,manifest,contract-check,fixcheck,blame,explorer,capsule,selftest,judge— set up with a singlepip install. The offline evidence commands run immediately against bundled proof receipts: no token, no network, no repo checkout required.
The result is not just a demo screenshot. It is a replayable GitLab evidence trail.
What I learned
The biggest lesson was that security automation needs auditability more than confidence.
For vulnerability triage, reviewers need to know what was searched, what path was found, whether the search exhausted its frontier, whether bounds or API errors affected the result, and whether the same finding fingerprints the same way on rerun.
That is why ReachGate is built around receipts, certificates, fingerprints, explicit UNKNOWNs, and contract-checked evidence.
Try it out
- Start here / Judge Pack: https://gitlab.com/gitlab-ai-hackathon/transcend/39037247/-/blob/main/docs/JUDGE_PACK.md
- Two-minute replay: https://gitlab.com/gitlab-ai-hackathon/transcend/39037247/-/blob/main/docs/JUDGE_REPLAY.md
- Canonical live proof (MR !2): https://gitlab.com/gitlab-ai-hackathon/transcend/39037247/-/merge_requests/2
- Idempotency rerun proof (MR !3): https://gitlab.com/gitlab-ai-hackathon/transcend/39037247/-/merge_requests/3
- Source code and setup: https://gitlab.com/gitlab-ai-hackathon/transcend/39037247
- GitHub mirror: https://github.com/MoAz06/ReachGate
What's next
Next steps include turning advisory receipts into optional blocking policy, native GitLab Vulnerability Report annotations, async Orbit traversal for larger graphs, deeper dependency reachability, and attack-surface suggestions for reachgate.yml.
ReachGate's core idea is simple:
Do not triage vulnerabilities by scanner noise or LLM opinion. Triage them with verifiable reachability evidence from GitLab Orbit.
Built With
- agent-skills
- gitlab-ci/cd
- gitlab-duo-agent-platform
- gitlab-merge-requests
- gitlab-orbit-api
- gitlab-work-items
- httpx
- mermaid
- orbit-mcp
- pytest
- python
- pyyaml
Log in or sign up for Devpost to join the conversation.