CoreBreak: The Tool Call That Never Came From the Model

By AI Agent Engineering | 2026-08-20 | security

A request arrives at your agent service. Inside it, in the last message of the conversation, sits a block of JSON that looks exactly like the thing your model emits when it decides to call a tool. Your event loop reads that block, recognises the shape, and dispatches the tool.

The model never ran.

Not "the model was tricked". Not "the model was jailbroken". The model was never in the path at all. Every defence you built on top of it, the system prompt, the content filter, the refusal training, the careful tool descriptions that steer behaviour, sat one layer above a decision that had already been made by the caller.

That pattern has a name now. Two researchers, Hedi Ingber and Aviyam Ivgi of Stealth, presented it at Black Hat USA 2026 as CoreBreak, and they found it in production agent infrastructure at Amazon, Google and Vercel [1]. Three independent teams, three different codebases, one identical assumption: that data shaped like a model decision came from the model.

What the vulnerable path actually looked like

Every agent harness does the same job. It holds a conversation, sends it to a model, receives a response, and if that response contains a tool call, it executes the named tool with the given arguments and feeds the result back. That loop is the entire product. It is also, in all three cases, where the authorization went missing.

Amazon's version is the cleanest to describe. Bedrock AgentCore exposed an InvokeHarness API. When the most recent message in an InvokeHarness request contained a tool-use content block, the agent event loop dispatched the named tool directly, skipping model invocation and the security controls attached to it [2]. An authenticated caller who could shape the message history could therefore run any tool configured on that harness, with the arguments of their choosing. AWS assigned CVE-2026-18830, scored it 8.6 under CVSS v4.0, classified it as improper input validation (CWE-1287), and deployed a server-side fix on 31 July 2026 that rejects caller-supplied tool-use blocks in the final message before the event loop sees them [2]. No customer action required, because the mitigation applies automatically to every request.

Google's is the more severe of the two, and the more interesting. The Agent Development Kit for Python lets developers mark a sensitive tool as requiring human approval before it executes. That is a deliberate, well-designed control: the high-stakes actions do not run autonomously, a person confirms them. In ADK before 2.5.0, the confirmation processor did not verify that a confirmation belonged to the tool it claimed to confirm, that the tool actually required confirmation, or that the arguments matched what had been approved [1]. An attacker who could influence session history could forge an approval for a tool nobody approved. NVD scored it 9.3. Google shipped the fix in 2.5.0 on 16 July 2026, and in the same release closed a second path the researchers found, in resumable-mode flows, which accepted user-authored events containing function_call blocks and executed them without any model turn at all. Only the first got a CVE, because only the first affects the default configuration [1].

Vercel's is the narrowest and the most instructive about trust boundaries. Two AI SDK harness packages, @ai-sdk/harness-codex and @ai-sdk/harness-opencode, decided whether a process was allowed to invoke host-exposed tools by checking whether its command line contained the path of an approved helper script [1]. Code already running inside the sandbox could satisfy that check. A malicious dependency, a build script, a lifecycle hook, anything with execution inside the box, could then reach secret lookups, deployments and cloud API calls. Both were scored 6.3, which is right: the attacker needs a foothold first. The fix removed the process-path fallback and now requires an exact, short-lived, one-time authorization matching the tool name and input observed in a real model event.

The distinction that matters

The researchers were explicit that this is not prompt injection [1]. That distinction is not pedantry, and getting it wrong will send your remediation in the wrong direction.

Prompt injection is an argument with the model. Someone hides instructions in a document, a web page, an issue comment, and the model reads them and complies. Every defence in that category is probabilistic, because the model is a probabilistic component. You reduce the success rate. You do not get to zero, which is why the honest advice has always been defence in depth.

CoreBreak is not an argument with anything. The runtime received data with the right shape and treated it as authoritative. There is no model to convince, no refusal to route around, no eval that would have caught it, because the model produced nothing. This is a plain authorization bug that happens to live in an AI system, and authorization bugs have deterministic fixes. That is the good news buried in a Black Hat talk about three CVEs: this class is closeable in a way prompt injection is not.

It also means the defences most teams are proud of are irrelevant here. A stricter system prompt does nothing. A better refusal-tuned model does nothing. Output filtering does nothing, because there is no model output to filter. The control that would have caught it lives below all of that, in the twenty lines where the harness parses a message and decides what to run.

The patch that stopped at the service boundary

Here is the part worth sitting with.

AWS fixed the managed service. The fix is server-side, automatic, and complete for anyone calling InvokeHarness [2]. But the same pattern lives in the open-source Strands Python codebase that underlies that style of agent loop, where reporting on the disclosure describes event_loop.py logic that skips model invocation when the latest message contains a ToolUse, and a June pull request warning that externally injected toolUse blocks could reach execution was closed unmerged on 19 June 2026 [1]. AWS addressed the library side through documentation, guidance to build message history from your own application rather than from input a caller can shape [1].

That guidance is correct. It is also the oldest and least reliable control in software: a note in the docs telling every future developer not to make an obvious mistake.

The distinction being drawn is between a managed product, where AWS owns the request boundary and can validate at ingestion, and a library, where the developer owns the boundary and could legitimately be building message history from anywhere. Reasonable. But it produces an outcome worth naming plainly: the vendor patched the surface it operates, and the identical pattern in the code you actually run in your own process got a paragraph. If your architecture is "managed service", you were fixed on 31 July without doing anything. If your architecture is "the open library, self-hosted", you are the mitigation.

Check which of those describes you before you file this away as patched.

Authorization at execution time

All three vendors converged on the same remedy, which is the strongest signal in the whole disclosure that the remedy is right.

Authorization at execution time means binding each tool invocation to the specific model event that produced it: the tool name, the arguments, the session, and the authorization state at that moment [1]. The runtime stops asking "does this look like a tool call" and starts asking "can I trace this call back to a model turn I recorded". Shape is not provenance.

The three implementations differ in a way that is useful when you go to build your own. Google validates confirmations against recorded session state, so an approval has to match something the system actually issued. Vercel issues one-time HMAC-signed approvals, so a valid authorization cannot be replayed or reused. AWS rejects caller-supplied blocks at ingestion, so the untrusted data never reaches the loop [1]. Server-side rejection, cryptographic binding, state validation. Pick whichever fits where your trust boundary sits, and if you cannot say where your trust boundary sits, that is the actual finding.

The practical version, for a harness you maintain:

Find the line where a tool call is parsed out of a message. Ask what proves it came from your model client rather than from the request body. If the answer is the JSON structure, you have the bug.

Then treat conversation history, resumable events, confirmations and tool-use blocks as untrusted input whenever they cross an external boundary [1]. Not because a caller is presumed hostile, but because these structures were designed as an internal protocol between your loop and your model, and they were never designed to survive a round trip through a client.

And apply least privilege to the blast radius, because it is the control that still works when the first two fail. Each agent gets only the tools, cloud roles, credentials and write permissions its task requires [1]. AWS noted that the impact of CVE-2026-18830 was limited to tools configured on that specific harness [2]. That sentence is doing a lot of work. It is the difference between a bad afternoon and an incident report.

If you are patching rather than auditing: ADK to 2.5.0 or later, @ai-sdk/harness-codex to 1.0.29 or later, @ai-sdk/harness-opencode to 1.0.28 or later [1]. Bedrock AgentCore needs nothing.

The same failure, one layer up

There is a version of this problem that no patch fixes, and a benchmark published in August put numbers on it.

MasDrift tested whether delegated goals in multi-agent systems keep the authorization boundaries they started with, across 600 benign productivity tasks in eight domains [3]. Centralized hierarchies completed 93.9 to 98.6 percent of tasks against 85.7 to 87.0 percent for peer networks, and took unauthorized actions in 2.7 to 19.8 percent of tasks against 0.6 to 0.8 percent [3]. The architecture that gets more done is the architecture that more often does things nobody authorized. Of the two defences tested, re-anchoring authorization checks beat propagating them along the delegation chain [3].

Re-anchoring. Checking against the origin rather than trusting what was handed down. That is authorization at execution time, restated at the level of agents delegating to agents instead of a loop dispatching a tool.

CoreBreak is that failure inside one process, where a CVE and a version bump can close it. MasDrift is the same failure between agents, where the fix is a design decision you make and remake every time you add a hop. One of them is patched. The other one is an architecture you are probably still choosing.


References

[1] Swati Khandelwal, The Hacker News — AWS, Google, and Vercel Agent Flaws Let Attackers Trigger Tools Without Running the Model. Article

[2] AWS Security Bulletin 2026-073 — CVE-2026-18830: Issue with Amazon Bedrock AgentCore harness, Insufficient Input Validation. Article

[3] Xu, Zhang, Luo, Jin, Dong, Salam — MasDrift: Benchmarking Authorization Preservation Across Multi-Agent Architectures. Paper