TL;DR: A bug-bounty target with sixteen domains, a clean first pass, and three hypotheses that looked like they could pay. So I ran 55 agent units against it in four waves — each unit a starting point on a shared map, findings landing in a ledger with a hash, a chair agent deciding after every wave what to test next. The deep units killed all three leads. This is how the orchestration works, and why the honest answer was worth more than a submission.
The premise
The first pass over the target was uneventful in the way that good engineering usually is: patch-current components, hardened error pages, authentication on every API that mattered, and four findings that were really hygiene notes. The programme's own rules exclude most of that class, so the report was worth little.
But there were three threads that could have been real:
- A wiki engine whose version is famously the difference between "fine" and "unauthenticated remote code execution".
- A CMS that also has an RCE history — with a public CVE whose affected range we suspected we were inside.
- A forgotten VPN appliance on a hostname that no longer resolves, still answering on the shared edge.
Each one needed evidence, not vibes. And each one needed a different kind of evidence: a version, a patch level, a build string. That is the kind of work that parallelises badly in a single thread and well across many.
The fleet
Fifty-five units, four waves, five running at once:
Wave 1 is breadth: one unit per domain plus four cross-domain sweeps for DNS and mail, TLS and certificate transparency, transport headers, and the exposure classics. Wave 2 is depth by class: API surface, CORS, shipped JavaScript, consent and tracking, supply chain, version-to-CVE matching. Wave 3 is the hypothesis layer — one unit per technology family, each with a specific claim to confirm or kill. Wave 4 is adversarial: a repro verifier, a false-positive killer, a CVSS calibrator, a chain builder, and an evidence-integrity unit.
Every unit writes the same contract: one JSON object per finding, with timestamp, severity, category, confidence, an evidence artefact, a SHA-256, a single repro command, an impact sentence and a fix sentence. No artefact, no finding. A hunch is allowed, but it must be labelled a hypothesis and must carry what would confirm it.
The map is the shared memory
Agents do not talk to each other. They talk to a file. The unit identity, the finding, and the decision that follows become nodes and edges in one mermaid graph, regenerated after every wave:
- units colour-coded by state — queued, running, done, failed
- findings hanging off the unit that produced them, coloured by severity
- meetings as a node with dotted "reports" edges from every contributing unit
- decisions as labelled edges from the chair — what runs next, and why
After wave 1 the map showed 45 findings, one real lead, and a queue of unanswered questions. The chair's decision edges then pointed at the units that could answer them. That is the whole orchestration trick: the map is not a picture of the work, it is the work queue.
Three leads, three verdicts
The wiki engine: patched. The version was readable, the CVE mapping was unambiguous, and it turned out to sit exactly on the fix release — current LTS. No finding, thread closed. This took one unit ten minutes.
The CMS: patch lag, but the door is not there. This is the interesting one, because the version was not published anywhere. So the unit fingerprinted it the deterministic way: hash the public bundle assets, compare against the official release tarballs, and use file modification times as the tiebreaker when two releases ship identical files. That pinned the core to a build eight months behind, inside the affected range of a critical RCE.
Then the second question: is the vulnerable route actually deployed? The CVE's attack path requires a component that turned out not to exist on the instance — the endpoint answered with the framework's generic 404. So the verdict was patch lag, not exploitable today: a medium finding with a clear fix, not an emergency.
The edge appliance: no version, no mapping. The forgotten VPN device answered on the shared origin, presented an expired factory certificate, and disclosed nothing about its firmware on any reachable surface. Without a build string there is no advisory to match, so the honest classification stayed exposure — worth reporting as unmanaged infrastructure, not as a CVE.
Two more falsifications came out of the same layer. A server-side URL proxy found in a shipped bundle looked like a potential SSRF primitive; the verification unit tested it with a self-fetch only, never a third party, and rejected it — not an anonymous fetch after all. And a stale DNS record on a reallocatable cloud address — a textbook takeover shape — turned out to be a provider-managed elastic address with no takeover possible; the unit documented the safe way for the owner to confirm it and closed the hypothesis.
The verification layer is not optional
Two things in wave 4 changed my opinion about running fleets like this.
The false-positive killer re-tested every claimed finding and threw two out, including one where the evidence artefact did not actually show what the summary claimed. That is the failure mode of parallel work: a confident summary that outruns its own evidence.
The evidence-integrity unit re-hashed all 160 ledger rows, checked that every artefact path existed, that the SHA-256 matched, and that the repro command still ran. It flagged the rows where the repro needed a working-directory hint and the three rows that were hypotheses rather than confirmations. Twenty minutes of work that turns a pile of claims into something a programme can audit.
Why the negative result is the result
The run ended with 160 findings: 4 high, 16 medium, and roughly 140 low and informational. Of the high ones, none survived verification into a CVSS 7+ with a proof of concept. Of the three leads that motivated the whole exercise, all three died under evidence.
That is not a failure. The programme's own rules exclude unverified hypotheses, headers-and-SSL best practice, and findings without a PoC — so submitting the three leads would have been noise at best and reputation damage at worst. What the fleet bought was certainty: a written, hashed, reproducible answer of "this route does not exist on this deployment" and "this build is not matched by any advisory we can find".
The four mediums that remain are honest work: patch lag on a CMS build, SPF and DMARC gaps on subdomains that make spoofing easy, a third-party ticketing iframe loaded before consent, and one analytics collector reflecting any origin with credentials.
What I would change next time
- Budget the wave-4 units from the start. Verification is where the value is, and I added it late.
- Give every hypothesis unit a kill criterion in the prompt. "Confirm or exclude, and say which" produces sharper work than "investigate".
- Keep the ledger as the only interface. The moment two agents coordinate through anything else, the map stops being the truth.
- Expect the map to point outward. The most useful decision edges in this run were the ones that closed branches, not the ones that opened them.
Takeaways
- A fleet is a queue and a ledger, not a conversation — the shared map is what makes parallel work auditable.
- Version-to-CVE work needs an exact build; hash-and-mtime fingerprinting beats guessing when the vendor publishes nothing.
- Test the attack path, not the version: a vulnerable build with an absent route is patch lag, not a breach.
- Verification units (repro, false positives, evidence integrity) are what separate a report from a pile of claims.
- A rigorous negative result is a deliverable. Submitted as noise, it would burn credibility that is much harder to rebuild than 160 findings took to gather.