Stolen or exposed credentials are involved in roughly a third of all confirmed data breaches, according to Verizon's 2025 Data Breach Investigations Report. When they're the root cause, IBM's 2025 Cost of a Data Breach study puts the average incident cost at $4.67 million — higher than the global average for breaches of any kind.
AI coding agents don't reduce that exposure. They expand it. An agent session can invoke dozens of credentialed tools in minutes, across cloud providers, databases, package registries, and internal APIs. The blast radius of a single compromised session is enormous.
The industry's response has been "inject credentials at invocation time, don't put them in the environment." That's the right principle. The implementation is where things get complicated — because most teams are only solving the easy part.
Credential injection is not an HTTP problem
When most platforms talk about credential injection, they mean HTTP tooling: swapping an Authorization header, populating an environment variable for a cloud CLI, patching a .netrc file. These are all cases where the credential travels over HTTP or is read from a text-based config.
Your developers don't only use HTTP tools.
Postgres speaks libpq wire protocol. MySQL speaks its own binary protocol. MongoDB uses the OP_MSG format. Redis uses RESP. Every one of these establishes a TCP socket connection and negotiates credentials as part of a binary protocol handshake — not as an HTTP header you can intercept and replace.
Safe credential injection for database connections requires understanding the protocol itself: when during the handshake to present the credential, how to verify that the right credential reached the right socket, and how to ensure it doesn't persist in memory or on disk after the connection closes. This is fundamentally different from what HTTP-centric injection frameworks provide.
Most agent platforms don't address this at all. Teams end up with database credentials in environment variables — exactly the pattern credential injection is supposed to replace — because there's no other mechanism that handles TCP socket protocols.
Where does the credential actually go?
Even when you have a working injection mechanism, there's a second problem: destination verification.
When your system hands a credential to a subprocess, how do you verify that subprocess is what it claims to be? A tool binary that accepts arbitrary arguments can relay a credential to any endpoint. A subprocess can spawn child processes that the parent process never directly observes. A malicious script hiding in a postinstall lifecycle hook can intercept the credential before the intended binary ever receives it.
Destination verification — confirming that a credential you inject actually reaches the intended process, authenticated to the intended host — is unsolved for most agent platforms. The assumption is that aws s3 cp is just aws s3 cp. That assumption is exploitable.
Docker creates a completely separate egress surface
Every docker build invocation creates a new network namespace. Every docker run creates a bridge network. Both have outbound internet access by default — Docker's own networking documentation confirms that containers use NAT/masquerading to reach external networks unless you explicitly configure otherwise.
This matters because it means RUN instructions in a Dockerfile execute in a network context that's independent of any proxy or egress control sitting in front of the agent process. A RUN apt-get install or RUN curl inside a Dockerfile has full outbound internet access during the build, entirely bypassing your egress monitoring.
The Dockerfile is often code the agent just wrote. CVE-2024-21626 — the "Leaky Vessels" runc vulnerability from early 2024 — demonstrated that build-time container execution can reach the host filesystem in ways that weren't anticipated. Build-time egress is not an edge case.
Authentication is not authorization
Say you've solved credential injection for your database connections. The agent authenticates safely to Postgres. Now what?
Authentication answers "who are you?" Authorization answers "what are you allowed to do?" Credential injection only addresses the first question.
An authenticated agent can run DROP TABLE. It can TRUNCATE. It can DELETE FROM users WHERE 1=1. It can alter schemas, remove indexes, and run queries that take production down for hours. Redis exposes FLUSHALL. MongoDB allows dropping collections with a single command. These operations require nothing beyond a valid authenticated connection.
The correct access model for an agent working on a specific task is least-privilege authorization scoped to that task: read-only where reads suffice, write access scoped to specific tables where writes are needed, and everything else blocked. Not at the credential level — at the statement level, enforced on what the agent actually sends over the wire.
Role management is operationally broken
The principle is clear: scope every agent session to exactly the permissions it needs. The practice is painful enough that almost nobody does it.
Creating a time-limited Postgres role scoped to specific tables, that expires when the session ends, revoked cleanly even if the session crashes. Doing the same for Redis, MongoDB, and MySQL in the same workflow. Coordinating this with cloud IAM to ensure the cloud credentials attached to the session have commensurate scope. Automating all of it reliably across your team's entire fleet of concurrent sessions.
The operational cost of doing this manually is high enough that teams default to a shared service account with permissions sized for the hardest use case — and use it for everything. The result: every agent session has the blast radius of your most permissive task, running as a credential that never expires.
Credential security for AI agents requires addressing the full stack: TCP socket protocols, destination verification, Docker build egress, per-statement authorization, and automated session-scoped role management. Marshal was built to cover this from end to end — because solving only the HTTP layer is not solving the problem.
The companion piece to this article covers the other half: how data leaves agent sessions — and how to catch it →
Marshal secures AI agent sessions across the full credential surface — database wire protocols, Docker egress, per-statement database policy, and per-session role scoping. Request access →