# Three gates for an offensive agent

By Derik Callahan · 2026-08-22 · https://derikcallahan.com/writing/three-gates-for-an-offensive-agent

> I built an MCP server for HackerOne and a bug bounty pipeline around it. The interesting part isn't the 174 tools. It's the three places where the agent has to stop and wait for me.

I wanted to find out how far an AI agent can go in bug bounty work, so I built the tooling to try. The first piece was an MCP server for the full HackerOne REST API: both the Customer and Hacker sides, 174 tools, running over stdio locally or hosted over Streamable HTTP. With it, an agent can read program policies, check scope, pull its own report history, and draft submissions.

That was the easy part. A model that can call 174 tools will happily call all of them. What took real design work was deciding where it must not act on its own.

## The pipeline

The work runs as a pipeline, and the human decisions are explicit steps in it, not a matter of the agent being polite:

1. **Rank programs.** A scoring script reads public program data and ranks targets. Read-only. Nothing touches a target.
2. **Gate 1: pursue.** The harness writes a proposal. I approve or reject it with a command that records the decision. No approval, no engagement.
3. **Onboard.** The engagement gets its own folder, a snapshot of the program policy, and a written scope file.
4. **Gate 2: authorized to test.** This is the line before any packet leaves the machine. The agent has to show that the target, technique, and rate limits map to the written scope.
5. **Recon, mapping, micro-scoped testing.** One bug class per run, passive before active.
6. **Reproduce or discard.** If it doesn't reproduce on the live in-scope target, there's no report.
7. **Gate 3: submit.** Nothing goes to a program under my name until I've read it.

## Why gates, not prompts

You can tell a model "only test in-scope assets," and most of the time it will listen. But "most of the time" is the wrong standard when the failure is unauthorized access to someone else's system. A rule written in a prompt is a suggestion. A gate is a control: the next step physically can't run until a decision has been recorded.

Each gate puts a person at the point where the stakes change:

- **Gate 1** is a business decision: is this worth my time?
- **Gate 2** is a legal one: am I allowed to do this?
- **Gate 3** is about reputation: am I willing to sign this?

Between the gates, the agent is free to go fast. That's the trade I'd make in any company too. Let automation run hard inside a box, and put humans on the edges of the box.

## What carries over to the enterprise

This is the same pattern I use for agents at work, just applied to offense. The terms there are destructive-action controls and approval gates on high-impact operations. But the shape is the same:

- **Sort actions by blast radius, not by tool name.** Reading a policy and submitting a report can go through the same API client. They aren't the same risk.
- **Record the approval as data.** A Slack thumbs-up doesn't count. The approval should be a record the next step checks, with who approved it, when, and what exactly they approved.
- **Make the safe path the fast path.** If the gate is slow, people will build their way around it. My approvals are one command.

The tooling makes the agent capable. The gates make it something I'm willing to run.
