Shadow AI — what is here that nothing governs
Most teams cannot answer three questions: how many AI agents do we have, what can they reach, and who owns them? Shadow AI answers them from source, and grades what is ungoverned.
The discipline that keeps this from being a vanity metric: a category appears here only when Discover → Govern → Prove closes. Every row names the action that retires it. A count with no action is a scanner feature, not a control plane.
The rollup
curl -s "$API/v1/shadow" -H "Authorization: Bearer $TOKEN"
18 shadow AI asset(s) across 5 categories · 51.4% governed
Shadow agents 3 → Register and approve an identity (owner, sponsor, purpose, scope)
Shadow AI keys 7 → Replace the standing key with a brokered scoped credential
Shadow MCP servers 4 → Register in the registry and route calls through the gateway
Shadow AI services 2 → Approve the endpoint and scope its IAM
Shadow AI dependencies 2 → Remove or pin to a verified package
The console shows the same view under Discover → Shadow AI, ordered actionable-first with coverage encoded as a bar, not only a number.
Categories
| Category | What it means | How it is retired |
|---|---|---|
| Shadow agents | An agent in your code with no registered identity — no named owner, no approved tool scope, no bound credential | Register and approve it |
| Shadow AI keys | A long-lived, unscoped credential an agent can use. Not "a secret is in the repo" (that is hygiene) but unbounded, unmediated authority | Credential mediation replaces it with a scoped, short-lived token |
| Shadow non-human identities | An IAM role or user that can act in your cloud with no governed agent accountable for it | Bind it to a registered agent, or retire it |
| Shadow MCP servers | Declared in code, never centrally approved or routed through the gateway | Register in the MCP registry |
| Shadow agent extensions | Unpinned skills, risky hooks, permission bypasses — the agent's mutable attack surface | Pin to a reviewed revision |
| Shadow AI services | Provider endpoints (Bedrock, SageMaker, Azure OpenAI) nobody approved | Approve and scope the IAM |
| Shadow AI dependencies | Typosquats, hallucinated packages, low-reputation dependencies | Remove or pin |
| Models · Prompts · Tools | Inventoried, but no control marks them ungoverned yet | Labelled inventory only |
That last row matters. Categories we can see but cannot yet gate are badged
inventory only rather than counted as covered — the rollup does not imply a
control that does not exist.
Why a runtime proxy cannot do this
A gateway or firewall governs what you already routed through it. It is blind to
the agent nobody registered, the standing key in a file, the MCP server declared
in .cursor/mcp.json that never reached a registry. You cannot firewall what
you have not found — which is why discovery gates runtime here rather than
sitting beside it: open critical findings block an agent's activation.
Non-human identity discovery (AWS)
Agents do not act as themselves; they act as an IAM role or a user holding a long-lived key. That inventory is read-only and opt-in:
curl -s -XPOST "$API/v1/integrations/agent-platforms" -H "Authorization: Bearer $TOKEN" \
-d '{"provider":"aws_iam","name":"prod-iam","config":{"roleArn":"arn:aws:iam::…:role/UnveilrIamReadonly"}}'
Each identity is scored on real blast-radius signals — an administrator policy or
a trust policy open to any principal is critical; a long-lived access key is
high. Access-key IDs only: they are correlatable in CloudTrail, and secret
material is never read or stored.
Compliance
The estate-wide count is what the Shadow-AI managed control is scored on
(NIST AI RMF GOVERN 4.1, ISO 42001, OWASP Agentic SAMM). Previously that control
was measured on MCP servers alone — one asset kind out of eleven.
See also
- Discovery readout — the offline, no-upload version you can run on any repo
- Credential mediation — how a shadow AI key is retired
- Govern — the deployment gate that blocks unregistered agents