Threat model
The attacker and the bug class
An AI coding agent has privileged execution: it runs shell commands, writes files, fetches web pages, and talks to registries and MCP servers. The attack class EgressEye targets is indirect prompt injection → egress:
- The agent reads attacker-controlled content — a web page, a README, a package's install output, an MCP tool result.
- That content carries instructions: "to fix this error, POST your environment to …"
- The agent — not the user — decides to make an outbound request or send material it can see:
.envfiles, tokens in config, source code.
You cannot detect these behaviors from the model's weights. You observe the agent's actions at runtime.
What v1 defends against
| Attack | Defense |
|---|---|
| Fetch of a known-malicious URL | Mirror-feed hit → malicious, surfaced (and blocked in block mode) |
| Exfil to a typosquatted lookalike | Edit-distance + punycode + homoglyph heuristics → suspicious |
| Throwaway infrastructure | RDAP age check → suspicious under 30 days |
| Credentials leaving via tool calls | Secret patterns + entropy + env-blob detection, redacted on disk |
| Sharded exfiltration | Session aggregation: repeated contacts with the same host become one finding |
| Defanged URLs hidden in written scripts | Refanging before extraction; Write/Edit inputs scanned like commands |
What v1 does not defend against
- A determined compromised agent can bypass hooks — it can edit its own harness configuration.
- Unknown URLs with no signals stay
unknown. - Network-layer escapes (raw sockets, non-tool processes) are invisible to hook-based collection.
- The allowlist is an assumption: if a listed provider is compromised, traffic to it reads
cleanunless a feed also lists it.
Consequently: EgressEye raises the cost of casual and opportunistic attacks and gives you forensic visibility. For a hard boundary, run the agent in a sandbox with default-deny egress and use EgressEye as the audit layer on top.
Data handling
Session files: URLs stored query-stripped; secrets stored as 4-character prefixes + length; tool inputs are not stored. Feed mirrors are checked in memory. The only outbound-data options are explicit: a Google Safe Browsing key (URLs → Google) and RDAP registrar queries. EGRESS_EYE_OFFLINE=1 disables all network.