The Chat Endpoint Became a Network Proxy

The Chat Endpoint Became a Network Proxy

A chat endpoint can become a network proxy without adding a proxy feature.

That is the uncomfortable lesson in two Laravel security fixes published this week. One issue let a client supplied file URL make the application server fetch internal addresses. The other weakened validation around OAuth loopback redirects in Laravel MCP.

Neither bug requires a novel model attack. Both are ordinary trust boundary failures that become more consequential when an AI adapter sits in the middle of the request path.

What changed

The Laravel AI advisory affects laravel/ai versions 1.0.0 through before 1.0.1. Its Vercel AI SDK and AG-UI adapters accepted file parts containing URLs supplied by the client, then fetched those URLs from the server without sufficient validation.

The advisory rates it moderate, with a CVSS 3.1 score of 5.3. It requires an application to expose one of those adapters to untrusted clients. The problem is not that every Laravel AI application is automatically vulnerable. The problem is that a common attachment feature turned an input field into a server side HTTP client.

The Laravel MCP advisory describes a separate low severity OAuth redirect weakness. The affected releases are older than 0.9.6 on the 0.x line and older than 1.0.1 on the 1.x line. The fix validates loopback redirects by parsed scheme and host instead of a string prefix, and rejects redirect URIs containing userinfo.

These are separate vulnerabilities. They point at the same engineering mistake: treating structured security inputs as harmless strings.

The AI adapter crossed the boundary

The SSRF path is straightforward:

  1. An attacker sends a chat request containing a file part with a URL.
  2. The adapter accepts the URL as if it were an ordinary remote attachment.
  3. The Laravel application fetches it from its own network position.
  4. The response is passed to the model as a file attachment.

That last step matters. This is not only a blind request primitive. The advisory says the response body can end up in the model’s reply. A server that can reach a cloud metadata service, localhost endpoint, or private network may also expose the fetched content through the conversational interface.

The patched code path does more than reject one obvious hostname. The advisory says version 1.0.1 accepts only HTTP and HTTPS, blocks loopback, private, link-local, CGNAT, reserved, and NAT64 embedded addresses, checks every redirect hop, and pins the connection to the addresses it checked to prevent DNS rebinding.

That is the right shape of fix because the dangerous value is not merely a string. It is a destination that will be resolved, redirected, connected to, and then interpreted by another system.

Why MCP makes redirect parsing relevant

The MCP issue looks smaller because it is not an AI model exploit. OAuth redirects are still part of the agent boundary, especially when a desktop or local MCP client opens a browser flow and then listens on a loopback address.

The Laravel MCP patch says loopback redirect URIs now match on the parsed scheme and host, not a string prefix. It also rejects usernames and passwords in the URI. The 0.x backport is documented in pull request 351.

The difference between string matching and URL parsing is not cosmetic. A URL contains authority, credentials, scheme, port, path, and encoding rules. A prefix check can appear to accept the intended loopback target while failing to describe where a browser will actually send the user.

The release notes show the fix shipped in v1.0.1 and v0.9.6. The safe operational response is to update rather than reproduce the patch as application code.

The common intuition is wrong

The usual reaction to an SSRF report is to add a blocklist. The usual reaction to an OAuth redirect issue is to add another string comparison.

Both responses miss the mechanism.

The security property has to be defined at the point where the value becomes an action. For a remote file, that means validating the parsed destination, resolving it safely, checking redirects, and constraining egress. For OAuth, it means parsing the redirect URI and comparing the fields that the protocol actually uses.

This is also why model level defenses are irrelevant here. A model can be perfectly aligned and the application can still fetch an internal endpoint before the model sees the bytes. The model is downstream of the trust decision.

What operators should do

If you run Laravel AI:

  • Upgrade laravel/ai to 1.0.1 or later if the Vercel or AG-UI adapters accept untrusted chat requests.
  • If an upgrade is not possible, reject URL based file parts before they reach the adapter.
  • Restrict outbound network access from the application process, including metadata and private address ranges.
  • Treat redirects and DNS resolution as part of the validation decision, not as an implementation detail.

If you run Laravel MCP:

  • Upgrade the 1.x line to 1.0.1 or later, or the 0.x line to 0.9.6 or later.
  • Review any local OAuth client that performs its own loopback redirect checks.
  • Test parsed scheme, host, port, and userinfo behavior rather than relying on string prefixes.

The broader rule is simple: label every value that crosses from a client into a network action. A file URL is not just content metadata. An OAuth redirect is not just a callback string. Both are instructions to move data or a user across a trust boundary.

The adapter is part of the attack surface

AI integrations are often reviewed as model plumbing. That is a mistake.

An adapter decides which client fields become network requests, which responses become model context, and which redirects become browser navigation. It is security critical code even when its public API looks like a convenience wrapper around a chat message.

The model is only one component in the loop. The connector, URL parser, resolver, egress policy, browser handoff, and audit trail determine what the loop can actually do.

The chat endpoint did not become dangerous because the model got smarter. It became dangerous because an adapter gave client input a network identity.

Sources

Keep reading