Auditing AI agent DNS

With yeet, you can see every domain your agents look up and connect to, tied to the agent that asked.

curl -fsSL https://yeet.cx | sh

Linux only  |  Manual install  |  Read the docs

When the agent’s transcript isn’t enough

yeet comes in when the agent says one thing and the network says another. We sit alongside your DNS logs and EDR, and add what they can’t see: which agent, and which process, asked.

Your agent without yeet

npm install, run by the build agent

  • what did the agent run?The transcript says npm install, exit 0.
  • what did it look up?Resolver logs show the host asked. Not which process.
  • where did it connect?VPC flow logs show port 443 to a CDN address. No name.
  • did anything leave?Nothing in the agent’s own logs.

A guess: “npm telemetry, probably fine.” The rest waits for the security team.

Your agent with yeet

npm install, run by the build agent

  • what did the agent run?npm install, which started node to run a dependency’s postinstall script.
  • what did it look up?340 lookups for 60-character hex names under cdn-metrics.example, all from that script.
  • where did it connect?Nowhere new. The data went out inside the lookups themselves.
  • did anything leave?About 10 KB, encoded in the names, in under a minute.

A verdict: it’s data leaving over DNS. A postinstall script that the agent’s npm install ran encoded data into its lookups. Remove the package, block cdn-metrics.example, and rotate anything the agent’s user could read.

Agent DNS allowlists

The probe your agent writes for one incident doesn’t have to go away. yeet can run it as a service on the host, all day.

yeet learns the names each agent needs and serves the list to your CI. Anything new fails the run, and the rest can be blocked at the kernel.

  • A Slack alert when an agent looks up a domain it has never used
  • A per-agent allowlist, enforced at the kernel
  • A Prometheus metric for lookups per agent and per domain
  • A DNS tunneling detector for long, random names
Agent DNS allowlists, as a loopOn your host, a yeet service watches every lookup and connection your agents make and serves the names each one needs as an allowlist over an HTTP route. Your CI runs agent tasks against the list. A run that reaches a new domain fails.your agentslookups and connectionsyeet serviceruns all dayallowlist routeserved over HTTPCI test suiteagent runs against the listdeploya new domain fails the runwatchespulls the listshipsevery agent run is held to the names it is allowed to reach

How your agent works with yeet

Three layers yeet can read, from the agent down to the packet.

  • Agents

    Which agent asked, and everything it started.

    Claude Code, Codex, Cursor, MCP servers

    • Which domains did each agent reach?

      Every name an agent’s process tree looked up or connected to, grouped by agent and by session.

    • What did the agent’s child processes reach?

      npm, pip, git, curl and the shells the agent started, each tied back to the agent.

    • Which MCP server is talking to the internet?

      Outbound names per MCP server process, separate from the agent that launched it.

    • Which agent is calling which model API?

      Lookups and connections to model providers, per agent, with request counts.

  • Lookups

    What was asked, and what came back.

    DNS, DNS over HTTPS, systemd-resolved

    • What did the agent look up?

      Every query and answer, from the wire, from the system resolver and from DNS over HTTPS, tied to the process that asked.

    • Is something tunneling data over DNS?

      Long, high-entropy names, bursts of TXT queries and lookups that never lead to a connection.

    • Did it pull from a registry that isn’t ours?

      Lookups for package registries and mirrors, so a typosquatted or unexpected source stands out.

    • Which lookups failed?

      NXDOMAIN and SERVFAIL per agent, often the sign of a prompt-injected URL or a hallucinated host.

  • Connections

    Where the agent actually went, even with no lookup to see.

    TLS, TCP, the kernel

    • Where did it connect without a lookup?

      Names read from the TLS handshake, for connections to hard-coded addresses or cached answers.

    • Did the name match the address?

      The name a process looked up against the address it connected to, so a swapped answer shows up.

    • What did the agent try that was blocked?

      Denied lookups and connections per agent, with the process that tried them.

    • How much did each agent send, and where?

      Bytes out per agent and per destination, named.

Make your machines readable

See every domain your agents reach, in under a minute.

curl -fsSL https://yeet.cx | sh

Linux only  |  Manual install  |  Read the docs