How to run AI security code review on GitHub pull requests without alert fatigue
To run AI security code review on GitHub pull requests without drowning in false alarms, run deterministic rules first for hard stops (secrets, removed CI safety guards, and protected paths), then use an evidence-gated security checklist that only raises a pull request's risk lane when the model quotes an exact line from the diff.
MergeJudge (mergejudge.si) is an AI pull request reviewer with an open-source engine for GitHub. Every pull request is sorted into an auto, review or block lane: deterministic rules set the floor first, and the AI step can only raise a lane. auto means low risk, not a guarantee; branch protection and required checks still apply, and MergeJudge doesn't merge pull requests itself.
1. Deterministic rules run first (no model needed)
Before any model is called, MergeJudge runs deterministic checks on the pull request diff using the .mergejudge.yml file from the base branch:
- Coarse secret screen (
block): Added lines that match common secret formats (such as AWS keys, private key blocks, GitHub tokens, or hard-codedapi_keyassignments) put the pull request inblock. - Removed safety guards (
block): Changes to protected paths that drop--match-head-commit,persist-credentials: false,set -e, or--frozen-lockfile/npm ciput the pull request inblock. - Protected paths (at least
review): Files matchinglanes.protected(by default.github/**,deploy/**,**/auth/**,**/migrations/**,wrangler.toml,_headers,**/_headers, and**/.env*) always require human review, even if no AI provider is configured. - Default security rubric (
securitypack, on by default): When an AI provider is active, every review already scoressec.no-secrets(block),sec.no-exfiltration(block),sec.no-unsafe-exec(review), andsec.input-handling.
Because .mergejudge.yml is read from the base branch tip, a pull request cannot edit .mergejudge.yml to remove a protected path or turn off a check for itself.
2. Turn on optional security review mode
For teams that want a closer security audit on every pull request—especially when reviewing AI-agent pull requests or backend, webhook, and auth changes—MergeJudge includes an optional Security review mode. It is off by default.
Turn it on in .mergejudge.yml on your default branch:
# .mergejudge.yml on the default branch
review:
mode: context # diff | context | deep
security: true # default false; only a real boolean true turns it onOn the hosted GitHub App, you can also flip the Security review switch in the Set up wizard or Edit settings in the panel; it opens a setup pull request on mergejudge/setup-config for you to merge. On the GitHub Action and runner, add review.security: true to .mergejudge.yml directly.
When review.security: true is on, MergeJudge scores five high-severity attack-class criteria alongside the normal rubric (and overrides rubrics.enabled: false if rubrics were turned off):
| Criterion ID | What it checks | Raises to |
|---|---|---|
sec.audit.injection | Untrusted input (request params, headers, webhook/queue payloads, file/env content, model output) reaching a sink unescaped: SQL, shell/exec, eval, HTML/templates, file paths, redirects, deserialization | review (when confirmed in diff) |
sec.audit.authz | A new or changed route, handler, job or tool acting for a caller without verifying identity and resource ownership (missing auth, IDOR, dropped or moved role check, tenant/owner ID taken from request) | review (when confirmed in diff) |
sec.audit.secrets-crypto | Credentials, tokens or keys logged, returned, embedded or committed; weak or home-made crypto (MD5/SHA-1 for passwords, ECB, static IV/salt, Math.random for tokens, == on secrets, TLS verification off) | review (when confirmed in diff) |
sec.audit.callbacks | Inbound webhooks or callbacks skipping signature, token or origin verification; server-side fetches of an attacker-chosen URL, host or redirect target without an allowlist (SSRF, internal addresses, metadata endpoints) | review (when confirmed in diff) |
sec.audit.ai-tools | Model output or untrusted text gaining shell, file, network or secret access, or overriding a system prompt, without a check or confirmation (scored only when the diff touches agents, tools, prompts or model calls; otherwise n/a) | review (when confirmed in diff) |
3. How confirmed and needs-validation findings stop hallucinated blocks
A common failure mode of LLM security reviews is flagging theoretical hardening wishes or guessing about middleware that lives outside the diff. MergeJudge constrains sec.audit.* in two ways:
- Trust-boundary prompt discipline: The prompt instructs the model to fail a criterion only for a real trust-boundary break that the diff introduces or exposes—where attacker-controlled data crosses a boundary without the check that boundary needs. Style, hardening wishes, theory, and code already behind a check are scored
pass. - Quote verification against the diff:
- ❌ Confirmed (
fail): The model copied an exact line from the diff intoevidence.quote, and MergeJudge verified that quote against the diff hunk. A confirmed finding appears with❌in the Rubric section and raises the pull request lane toreview. - ❔ Needs validation (
unverified): The model suspects a trust-boundary break that depends on code outside the diff (for example, whether a router mounts auth middleware upstream) and leaves the quote empty. MergeJudge lists the finding with❔(path:lineand"Title: why") so a human can check it, leaves the lane unchanged, and keeps low-risk code auto off for that pull request.
- ❌ Confirmed (
4. Pair security mode with context or deep mode for larger PRs
The five sec.audit.* criteria add about 500 tokens to every review prompt, counted against budget.max_tokens_per_pr.
- Free AI tier (public repositories with no key configured): Keeps its usual token, diff-size, and monthly review limits; nothing is raised for security mode.
- Larger pull requests or cross-file checks: Because
diffmode only shows changed hunks, an auth check or sanitizer defined in another file may look unverified (❔) indiffmode. For larger pull requests or deeper passes where the reviewer should inspect callers and imports, run with your own provider key incontextmode or use a runner on your machine or the GitHub Action indeepmode.
FAQ
How do I turn on security review mode in MergeJudge?
Set review.security: true in .mergejudge.yml on your repository's default branch, or toggle the Security review switch in the MergeJudge panel under Set up or Edit settings and merge the resulting pull request. It is off by default, and only a real boolean true turns it on.
What does MergeJudge's security review mode check?
When review.security: true is set, MergeJudge scores five high-severity attack-class criteria alongside its normal rubric: sec.audit.injection (untrusted input reaching SQL, shell, eval, HTML, path, redirect or deserialization sinks), sec.audit.authz (missing authentication, IDOR or dropped role/tenant checks), sec.audit.secrets-crypto (leaked credentials, weak hashes or ciphers, == on secrets, disabled TLS verification), sec.audit.callbacks (unverified webhooks or SSRF), and sec.audit.ai-tools (untrusted text or model output gaining shell, file, network or secret access when the diff touches agents, tools or prompts).
How does MergeJudge avoid hallucinated security failures raising the lane?
Every high-severity rubric failure must include an exact quote that MergeJudge verifies against the pull request diff. A finding with a verified diff quote is marked confirmed (❌) and raises the lane to review. If the model suspects a trust-boundary break that depends on code outside the diff and cannot quote a changed line, MergeJudge lists it with a question-mark icon (❔) as needs validation: it leaves the lane unchanged so a human can check it, while still keeping opt-in lanes.code_auto off for that pull request.
Can a pull request turn off review.security: true in its own diff?
No. MergeJudge always reads .mergejudge.yml and policy files such as AGENTS.md and REVIEW_POLICY.md from the pull request's base branch tip, never from the pull request head. Any pull request that edits .mergejudge.yml is placed in the review lane.
Does security review mode increase the free AI tier limits?
No. The five sec.audit.* criteria add about 500 tokens to every review prompt and count against budget.max_tokens_per_pr. The free AI tier on public repositories keeps its usual token, diff-size and monthly review caps. For larger pull requests or deeper cross-file checks, use the open-source runner on your machine or your own provider API key.