Detecting shadow AI: what EDR, CASB and a local scan see
A developer installs Cursor to ship a feature faster. It gets read and write access to the repository, and it inherits whatever is already in the shell: the cloud keys, the database URL, the production token exported for a quick test. From that moment an autonomous process is acting with the authority of whatever credentials were in that shell. Your identity stack never recorded a thing, because nothing logged in.
The agent does leave a trail, but it is split across tools that answer different questions. An EDR sensor records its processes, the commands it runs and the hosts it connects to. A CASB or network proxy records the AI services it calls. None of their event logs holds the contents of the config file that says which MCP servers the agent can start and what each one may do. The coverage table below shows which tool observes which signal, with a source for every row.
Every shadow IT problem used to end up in a log
The reason shadow IT became manageable is that it left evidence. A new SaaS app showed up as an SSO login. An unsanctioned OAuth grant showed up in a CASB report. Unapproved software showed up in endpoint inventory. The discovery problem was solved by instrumenting the chokepoints every tool had to pass through: a login, a token, an installer.
A coding agent passes through fewer of them. Claude Code, Cursor, and Windsurf install with one command and run as an ordinary local process, and an API key in the shell stands in for a login. There's no login page and no OAuth grant your directory issued. What the agent leaves is a process, the processes it starts, its network connections and a handful of config files. Each of those shows up somewhere, in a different tool.
Each tool records a piece. None of their event logs holds the contents of the MCP config, the file that says what the agent may do.
Can EDR or CASB detect shadow AI?
Partly, and each sees a different part. The table lists the signals a coding agent produces, which of four kinds of tool can observe each one, the access that takes, and what stays unseen. A local scan means a tool run on the machine itself, such as opena2a detect.
The EDR rows cite Microsoft Defender for Endpoint's event tables, and the CASB and proxy rows cite Microsoft Defender for Cloud Apps and Entra Global Secure Access, because their schemas are published. Other vendors' tools keep similar records under other names; your own tool's documentation lists the fields it keeps.
| Signal | Who can observe it | Access it needs | What stays unseen | Source |
|---|---|---|---|---|
| The agent process starts: claude, Cursor, Windsurf | EDR, Local scan | EDR: its sensor on the device records each process created, with the command line and the parent process. Local scan: a run on that device, as the user, that reads the process list. | Which processes are AI agents: an EDR records every process, so a query, rule or inventory has to name them. What the agent was asked to do. |
|
| A command the agent runs: a shell, git, npx | EDR | EDR: its sensor on the device. The new process is recorded with the agent as its initiating process, so a query can list what the agent started. | The prompt or plan behind the command. A local scan reads the machine at one moment and records no commands. | |
| An MCP config file is written: .mcp.json, ~/.cursor/mcp.json | EDR, Local scan | EDR: its sensor records the file event. Local scan: read access to the file. | What the file grants, in the EDR record: the event holds the path, the hash and the process that wrote it, and the table has no column for the file's contents. |
|
| A local MCP server runs over stdio | EDR, Local scan | EDR: the client launches the server as a subprocess, so the launch is a process event with its command line. Local scan: reads the config file that declares the server. | The JSON-RPC messages on the server's stdin and stdout, which carry the tool calls. None of the four records them, and they never cross the network, so a CASB or proxy has nothing to log. | |
| Calls to a hosted model API, such as api.anthropic.com or api.openai.com | EDR, CASB, Network proxy | CASB: traffic logs from the firewall or proxy, or from its endpoint integration, matched against its app catalog. Network proxy: the traffic has to be routed through it. EDR: its sensor; the network event names the process that opened the connection. | Without TLS inspection, what was sent: a proxy forwards an HTTPS tunnel's data blind. By default a CASB does not discover an app missing from its catalog, such as a self-hosted model endpoint. | |
| A remote MCP server reached over HTTP | EDR, Network proxy | Network proxy: the traffic has to be routed through it. Entra Global Secure Access, for one, detects connections to SaaS MCP servers, and its Generative AI Insights feature logs MCP operations through TLS inspection. EDR: the network event names the destination and the process. | Without TLS inspection, the tool calls and their results. | |
| An AI chat used in a browser tab | EDR, CASB, Network proxy | CASB: traffic logs matched against the Generative AI category of its catalog. Network proxy: the traffic has to be routed through it. EDR: the browser process and its connections. | Everything, to a local scan: no agent process runs outside the browser and no config file is written. Without TLS inspection, what was typed or pasted into the chat. |
So the trail exists. What none of the event logs holds is the agent's configuration: which MCP servers it can start and what each one may do. That is the part a local scan reads, and the reason detect runs beside the tools above, not in place of them.
The agent is the one holding your credentials
A gap in the record would be a minor problem if these agents did minor things. They don't. An agent runs with delegated authority to read, write, and execute on the developer's behalf, and it inherits the credentials already present in the environment it started in. The process an EDR logs beside the developer's editor can reach source code, cloud accounts, and databases.
Then it grows. Many agents connect to MCP servers, and each server is another capability handed over: run commands on this machine, query this database, call this payment API. In practice, few developers who wire in an MCP server can say, a week later, exactly what they granted. The attack surface expands quietly, one config edit at a time, with no review, and with a record that names the file but not what it granted.
The scale is measured, even though your laptop isn't
The supply side of this isn't a guess. The OpenA2A Registry has trust-scored more than 293,000 MCP servers, AI skills, and A2A agents. Most of what a developer installs has never been checked against any of it. The components are cheap to add and almost never verified before they run.
We can't tell you how many are running on your machines, and we built it that way on purpose. opena2a detect runs locally and sends us nothing: no account, no upload, no callback. The only number that describes your environment is the one you produce by running it yourself.
Discovery is the first move, not the product
You can't govern what you haven't inventoried, so the first move is to read the part the event logs leave out. One command, no account, runs locally in seconds, and answers the only two questions that matter to start: what AI is actually running here, and is any of it governed?
npx opena2a-cli detectIt reads the process list and config files for the agents that leave a local footprint (Claude Code, Cursor, Windsurf, Copilot, and others), the MCP servers wired into each, and the AI config files that grant them permission. It describes each MCP server's capabilities in plain language, because “can run commands on your computer” is more useful to a reviewer than a JSON blob. Everything rolls up into a governance score with a recovery path, so the output isn't a verdict but a worklist.
Seeing an agent isn't governing it
Discovery is worth nothing on its own. It earns its place by making three outcomes possible.
Know what exists. The discovered inventory is the asset register your SOC 2 and ISO 27001 auditors keep asking for and your spreadsheet keeps failing to produce. It's machine-readable and diffable, so the baseline is a file in version control, not a memory.
Produce proof on demand. “Which ungoverned agents appeared this quarter” becomes a query instead of an investigation, because the output is structured JSON a SIEM can ingest.
Give each one an identity. A discovered agent gets a project identity and governance rules; a discovered MCP server gets a signed Ed25519 identity, so the next scan can tell a verified server from an unsigned one. That's the move from inventory to control.
The evidence outcome is the one a CISO will ask to see. A scan returns structured findings, and every finding carries its own remediation, so the path from a high-risk score to a governed one is the worklist the scan already handed you:
{
"summary": { "totalAgents": 1, "ungoverned": 1, "mcpServers": 14, "governanceScore": 45 },
"findings": [
{
"severity": "high",
"title": "No agent identity for this project",
"whyItMatters": "Without an identity there is no way to attribute what this agent did.",
"remediation": "opena2a identity create --name my-project"
}
]
}What detect won't do
It's a local discovery tool with real edges. It reads the process list and config files, so it finds agents that leave a footprint on disk. An agent that runs entirely in a browser tab, or a remote service you never configured locally, is outside its reach. It's not a network scanner and it's not an EDR.
And because it sends us nothing, there's no central dashboard of your fleet and no number we can quote back to you. That's a deliberate trade: privacy over telemetry. Discovery is also not governance. Finding an ungoverned agent changes nothing until you give it an identity and rules. The tool makes the problem visible. Closing it's still a decision you make.
Changes to this post:
- , replaced the claim that EDR, CASB and the other tools that made shadow IT visible are blind to agents with a table of what each one observes, with a source for every row. No measured value changed.
- Removed: “the tools that made shadow IT visible are blind to agents” and “no network traffic your SIEM recognizes as an agent.” Their vendors' documents say an EDR records an agent's processes, file writes and connections, and a CASB or network proxy records the AI services it calls.
- Added the coverage table: for each signal, which of EDR, a CASB, a network proxy and a local scan can observe it, the access that takes, and what stays unseen.
- Retitled from “Shadow IT always left a trail. Shadow AI doesn't.” to say what the post now shows.
Shadow IT got governed once we could see it. The logins, the tokens, the installers became chokepoints we could instrument, and visibility turned an unmanaged sprawl into an asset register. Shadow AI gets governed the same way. The seeing has to be joined up for agents that never log in: the process and network records your EDR and proxy already keep, and the configuration only the machine holds.
Where an agent runs on a developer's machine, it inherits their credentials, and the contents of its configuration are in none of those logs. The first move is one command that reads it.