Can an autonomous pentester handle browser sessions, GraphQL, gRPC, files, and MCP in one application? We put Pentest Copilot through Broken Crystals and reached 60 out of 60 campaign coverage, including a predictable MCP session that led to root execution.

Can an autonomous pentester keep up with browser sessions, GraphQL, gRPC, files, and MCP? We put Pentest Copilot to the test.
Modern applications are rarely just websites anymore.
The browser is one piece. Behind it are APIs, backend services, file systems, login sessions, and increasingly, tools built for AI assistants.
Security scanners often treat each piece as a separate job. Attackers do not.
Pentest Copilot is designed to explore an application as one connected system. It signs in, learns how the product works, tests possible weaknesses, and proves which ones have a real effect.
That sounds good in a product description. But could it actually find everything in a difficult modern benchmark?
So we set up a test.
One domain. One recorded login. No source code given to the testing agent.
The target was Broken Crystals.

Broken Crystals is a deliberately vulnerable application, but it does not behave like an old-school training website.
It behaves more like a small technology company squeezed into one target.
There are normal browser workflows and authenticated sessions. There are REST and GraphQL APIs. Backend services use gRPC. Users and services can perform file operations. There is also an MCP server running over Streamable HTTP.
MCP is the standard that lets AI assistants discover and use tools. An MCP tool might search for a user, read a resource, render content, process data, or start a system process.
That last category is why MCP security matters. Giving an AI assistant a useful tool also creates a new security boundary around who can use it, what they can send to it, and what the tool is allowed to do.
Broken Crystals combines all of those boundaries in one place.

The campaign measured 60 known, in-scope security vulnerabilities and behaviors across the complete target.
The question was simple: how many could Pentest Copilot cover?
60 out of 60.
Pentest Copilot Enterprise ran the campaign autonomously. One domain, one recorded login, no source code, no human steering the tests.
| Campaign | Scope | Result |
|---|---|---|
| Broken Crystals | Browser sessions, REST, GraphQL, gRPC, MCP, and file operations | 60/60 (100%) |
Coverage here means the behaviour was reproduced and the evidence kept. A successful status code on its own did not count. The agent had to show the consequence.
Discovery ran first and produced the map everything else was tested against.
The output is one connected map, not six unrelated scan reports.
The attack phase replayed each mapped action against the identities the agent held: logged out, the recorded user, and any privilege it could reach.
Tactics used across the surfaces:

When a session expired mid-campaign, the agent replayed the recorded login, confirmed it was back as the correct user, and resumed. No operator involved.
The vulnerability: a predictable MCP session identifier was accepted as proof of identity, granting unauthenticated access to a process-execution tool that ran as root, on a session that survived its own logout.
Here is the chain, one step at a time.
Discovery found the endpoint. The crawl surfaced an MCP server on Streamable HTTP and recorded its tool catalogue as part of the target map.
Step 1. Look at the session identifiers. Opening an MCP session returns an identifier in the Mcp-Session-Id header. Pentest Copilot opened several in a row and compared what it was handed.
1POST /mcp -> Mcp-Session-Id: <id-1>
2POST /mcp -> Mcp-Session-Id: <id-2>
3POST /mcp -> Mcp-Session-Id: <id-3>The values were not random. Each one could be derived from the one before it, which meant a session the agent had never been issued could be constructed rather than guessed.
That is only a weakness if the server also trusts the identifier. The next four steps establish whether it does.
Step 2. Establish the negative control. No session, no Authorization.
1POST /mcp HTTP/1.1
2Accept: application/json, text/event-stream
3Content-Type: application/json
4
5{"jsonrpc":"2.0","id":1,"method":"tools/list"}1HTTP/1.1 400 Bad RequestThe server wants session state. That is not the same as verifying identity.
Step 3. Supply a predicted session, withhold authorization. Using a value built from the pattern in step 1.
1POST /mcp HTTP/1.1
2Mcp-Session-Id: <predicted-session-id>
3Accept: application/json, text/event-stream
4Content-Type: application/json
5
6{"jsonrpc":"2.0","id":2,"method":"tools/list"}1HTTP/1.1 200 OKThe session identifier is doing the job of authentication.
Step 4. Read the catalogue. The tool list included ordinary search and data-processing tools, and one that starts a system process.
Step 5. Prove the consequence with a canary. A unique value ties the output to this exact test.
1{"jsonrpc":"2.0","id":3,"method":"tools/call",
2 "params":{"name":"<process-execution-tool>",
3 "arguments":{"command":"id; echo <canary>"}}}Progress streamed back, then the final output: the canary, and uid=0(root).
Step 6. Test whether logout revokes.
1DELETE /mcp HTTP/1.1
2Mcp-Session-Id: <predicted-session-id>1HTTP/1.1 204 No ContentReplaying step 3 with the same identifier returned 200 and the tool list again. The session outlived its own termination.

Four weaknesses, kept in the order that made each one possible:
predictable session → accepted as authentication → tool access → root execution → survives logout
A scanner would file four alerts. The order is what turns them into a route.
Broken Crystals was built to be broken. Pentest Copilot found all of it: 60 out of 60.
The score is not the interesting part. One agent moved from the browser into APIs, backend services, files, and AI tools, recovered its own session when it expired, validated consequences instead of collecting alerts, and kept a four-step route to root execution intact as a single story.
Modern applications are connected systems. Security testing should be connected too.