How an AI agent talked itself into an XXE — and was right Equixly's AI agent autonomously discovered an XML External Entity (XXE) injection vulnerability in the chat layer of a collaboration platform during a grey-box assessment. The agent identified a message-forward field as a likely XML sink from an OpenAPI specification alone, confirmed the flaw via out-of-band detection, and demonstrated impact including arbitrary file reads and server-side request forgery that exfiltrated cleartext database credentials. How an AI agent talked itself into an XXE — and was right Eugen Saraci, Alessio Dalla Piazza Table of contents Abstract XML External Entity XXE injection has been well understood in application security for over a decade. The question in 2026 is not what XXE is, but how an autonomous agent decides that a given parameter — one the API contract describes as ordinary JSON — is worth an XXE payload at all and then confirms the flaw when the application never reflects the result . This article walks through a validated finding by Equixly’s AI agent in the chat layer of a collaboration platform. The assessment was grey-box, conducted against the live application using the credentials of a single low-privileged user, without ever reading the code which happens to be open-source . Starting from nothing but an OpenAPI specification, the agent flagged a message-forward field as a likely XML sink and escalated it to XXE on the strength of a single non-erroring probe. And because it had built no reflection relation linking that input to any observable output, it confirmed the vulnerability out-of-band. We then confirmed the impact: arbitrary local file reads and server-side request forgery, chained to exfiltrate a cleartext database credential. How Equixly’s AI found the XXE The vulnerability was not found by manual code review or a lucky fuzzer. Equixly’s agent identified it autonomously during routine API security testing. Below is the methodology behind the discovery. A note on method before the details. Although the platform is open-source, this was a grey-box assessment conducted entirely against the running application, and the agent never read the source code. It was configured with the credentials of a single low-privileged user, i.e., an ordinary, non-administrative account set up for the test. Equixly’s AI agent worked with the live API in the way an authenticated attacker holding those credentials would. The inference, the escalation, and the exfiltration were all achieved at that ordinary user’s privilege level, not by reading the code that, in this case, happened to be public. Phase 1: Autonomous exploration The only input was an OpenAPI specification. There was no source code, and nothing in the contract suggested XML was in play anywhere. The endpoint, which forwards a chat message from one conversation to another, accepts JSON like everything else in the API. Equixly’s agent does not begin with payloads; it begins with the contract. During exploration, it builds a model of what each parameter is for: What it represents, where it travels, and what the backend likely does with it. It also builds reflection relations, a map of which input parameters reappear in outputs elsewhere, so it knows in advance where a value injected in one place is likely to resurface in another. The message-forward field stood out for a structural reason. A forwarded message is content that gets picked up, re-wrapped, and handed to another part of the system. That is the sort of value that tends to pass through a parser on the way, and not necessarily the one the public contract advertises. The agent flagged it as a candidate for XML handling based on the role it plays, not on any application/xml label. Phase 2: Context-aware probing Instead of spraying random payloads, the agent generated a context-aware input to test the hypothesis: a small, well-formed, and completely innocuous snippet of XML, dropped into a field where the API expected an ordinary value. This confirmed nothing on its own. There was no oracle proving the value had been parsed as XML, no echoed markup, no parser error. What came back was simply a clean, positive response: The backend accepted the request and did not choke on it. The XML had not broken anything. That is a far weaker signal than “It is being parsed.” But it was enough. A field that swallows structurally valid XML without complaint is a prime candidate for feeding a parser, and that absence of rejection was all the AI agent needed. Off the back of one harmless, non-erroring probe, it escalated on its own to external-entity payloads, with no human in the loop telling it “This looks like XML; try XXE next.” That inference, drawn from a thin signal, is the capability that separates an agent reasoning about an API from a scanner fuzzing it. Phase 3: Out-of-band confirmation With XXE on the table, the agent had to choose how to confirm it. The textbook in-band test injects an entity that pulls a local file into the reply and reads it straight off the HTTP response. It is satisfying when it works, but it only works if the parsed result comes back somewhere observable. This is where the exploration data paid off. The agent had built no reflection relation for the message-forward field. Nothing it had observed tied that input to any output parameter that echoed the value back. With no known place to read a reflected file from, in-band reflection was a bad bet. So the agent went out of band. Rather than hope for reflected output that the exploration data suggested did not exist, it injected an entity forcing the server to reach back out to Equixly-controlled infrastructure, and treated that callback as the confirmation :