나는 당신이 버그 현상금 발견을 제출하기 전에 자신과 논쟁하는 판사를 지었습니다.

작성자

카테고리:

← 피드로
DEV Community · holistis · 2026-08-11 개발(SW)

holistis

I built a judge that argues with itself before you submit a bug bounty finding

A few days ago I published data on what actually gets paid in smart contract audit contests. The short version: submitting everything you find is a bad strategy. Rejected and duplicate submissions cost you time, reputation, and sometimes a stake. Being selective about what you actually submit is worth more than volume.

So I built the tool I wish existed for that: Al-Mizaan Judge, a CLI that takes your finding and puts it through a strict, adversarial review before you spend a real Sherlock, Immunefi, or Cantina submission on it.

How it works

Two layers.

Mechanical gates run first, free, no API call. They catch the cheap, obvious kills: a trusted actor (owner/admin/governance) as the sole attacker, a deployer misconfiguration with no external attacker, an oracle-manipulation finding that never proves economic viability.

Adversarial debate runs for anything that survives that. A Defender agent argues the code is safe. An Attacker agent tries to break that defense. A Judge decides, walking through scope, reachability, threat model, invariant breach, protocol intent, and dollar impact in that order. If it goes three rounds, the final round restricts the Judge to only code citations that were mechanically checked against the code you actually provided. No rhetoric, only what’s in the code. Doubt always defaults to KILL.

A real example

I ran it against a textbook reentrancy bug:

function withdraw(uint256 amount) external {
    require(balances[msg.sender] >= amount, "insufficient balance");
    (bool ok, ) = msg.sender.call{value: amount}("");
    require(ok, "transfer failed");
    balances[msg.sender] -= amount;
}

Enter fullscreen mode Exit fullscreen mode

Verdict: SUBMIT CANDIDATE, 90 to 98% confidence across all three rounds.

The Vault.sol code is in scope, and withdraw() performs a classic checks-effects-interactions violation: it sends ETH via a low-level call before decrementing balances[msg.sender], with no reentrancy guard present. This is reachable by any untrusted external account, directly breaching the solvency/accounting invariant.

Then I ran it against a finding that sounds scary but isn’t: an oracle that falls back to a manipulable TWAP during Chainlink downtime.

Verdict: LIKELY REJECTED, one round, 72% confidence.

Fails Gate 5 (Impact): no dollar/TVL quantification from either side. Additionally, the finding’s trigger condition is fundamentally Chainlink-staleness-driven fallback behavior, which Sherlock’s SJIP-21 rule marks invalid as a primary finding.

That second one matters. It didn’t just say “seems fine,” it cited the actual platform rule that kills this specific pattern on Sherlock. That’s the difference between a generic “is this a bug” prompt and something that actually knows how contest judging works.

What it deliberately doesn’t do

No code execution, no Foundry builds, no repo scanning, no hosting. You run it locally with your own Anthropic API key. Your code never leaves your machine except to the API you’re already paying for directly.

Try it

export ANTHROPIC_API_KEY=sk-ant-...
npx al-mizaan-judge your-finding.md

Enter fullscreen mode Exit fullscreen mode

Repo and full format docs: https://github.com/holistis/al-mizaan-judge

One honesty note, because I’d rather say this myself than have someone find it: the mechanical gates encode Sherlock’s own published judging policy, not our own statistics. We haven’t yet statistically validated verdicts against a large, representative outcome dataset, that corpus work is still in progress and I’ll write about it when it’s real. Until then, treat this as a strict second opinion grounded in real audit methodology, not a proven hit rate.

원문에서 계속 ↗

코멘트

답글 남기기