Shadow AI Discovery
The gateway governs traffic that points at it. Shadow AI Discovery answers the other question: what AI is running in the organization that doesn’t? Collectors and scanner adapters run in your infrastructure — CI, a host, a scheduled job — and send cryptographically signed discovery events to the platform, which reconciles them against the real gateway configuration and surfaces the result in the AI Asset Registry as governed, ungoverned or unknown.

How events are ingested
Section titled “How events are ingested”Collectors POST events to POST /v1/discovery/events on the Control Plane. There is no admin JWT on this endpoint — the Ed25519 signature is the authentication:
- Register a collector key (
POST /v1/admin/discovery/collector-keys) — a base64 Ed25519 public key with atrust_tier:first_party·channel·customer·community. - The collector signs each event (canonical JSON, minus the signature block) with its private key and sends
signature: {alg: "ed25519", key_id, value}. - The platform verifies the signature against the registered key. Missing/bad signature or unknown/revoked key →
401.
Idempotency and dedup are built in: event_id is unique per tenant (a duplicate is a {"status": "duplicate"} no-op), and events deduplicate into one discovered asset per (tenant, asset_key) — re-discovering a dismissed asset re-activates it.
Two properties are platform-computed and never taken from the event:
- Confidence — strongest evidence wins (passive network 0.9 > active probe 0.7 > host-derived 0.5), multiplied by the collector key’s trust tier. A collector’s own confidence claim is ignored.
- Governance status — reconciled against live config: an
llm_endpointis matched tollm_providersby host, anmcp_servertomcp_servers.base_url, ana2a_agenttoagent_cards.source_url. Matched to an enabled row →governed; unmatched or disabled →ungoverned; no host to match →unknown.
The egress-log collector
Section titled “The egress-log collector”The broadest first-party collector reads destination hostnames from egress proxy, firewall or DNS logs (Zscaler, Palo Alto, Squid) and emits an llm_endpoint event per known AI-provider host — OpenAI, Azure OpenAI, Anthropic, Google (Gemini + Vertex), AWS Bedrock, Mistral, Cohere, Groq, Perplexity.
pip install brutor-discoverybrutor-egress-collector --input /var/log/squid/access.log \ --gateway https://control.example.com --key collector.keyEvidence lands as tls_sni, passive — the highest-confidence class.
BYO scanners: the ingest adapters
Section titled “BYO scanners: the ingest adapters”Already running an AI scanner? brutor-ingest converts its output into signed discovery events — no bespoke collector required. Four adapters ship in the Discovery SDK (catalog: GET /v1/admin/discovery/ingest-adapters):
| Adapter | Modality | Ingests |
|---|---|---|
cyclonedx-aibom |
static | CycloneDX 1.5/1.6 ML/AI-BOM from any code/container scanner (Cisco AI-BOM, Trusera, cdxgen) — models, SDKs, agent frameworks, MCP servers |
agentsonar |
runtime | Knostic AgentSonar process→domain AI classifications — traffic bypassing the gateway |
snyk-agent-scan |
config | Snyk agent-scan / mcp-scan — MCP servers from local client configs (Claude Desktop, Cursor, …) incl. tool-poisoning findings, skills, agents |
safedep-vet |
static | SafeDep vet ai discover / vet code scan — coding agents, MCP servers, IDE extensions, AI-SDK usage in Go/Python/JS-TS |
# Feed a CycloneDX AI-BOM from CIbrutor-ingest --adapter cyclonedx-aibom -i aibom.json
# Feed AgentSonar runtime classifications, thresholdedbrutor-ingest --adapter agentsonar -i pairs.jsonl --set min_ai_score=0.6What a discovered asset looks like
Section titled “What a discovered asset looks like”asset_type ∈ llm_endpoint · mcp_server · a2a_agent · inference_runtime · agent_framework · sdk_usage · unknown_ai, with provider/endpoint details, computed_confidence, governance_status (+ governed_ref when matched), lifecycle status (active · onboarded · dismissed), evidence count and first/last seen. Evidence rows carry the type (dns_resolution, tls_sni, netflow, process, env_var, package_manifest, config_file, well_known_probe, registry_entry, api_inventory), the collector and its trust tier.
Acting on discoveries
Section titled “Acting on discoveries”| Method | Path | Purpose |
|---|---|---|
| GET | /v1/admin/discovery/assets |
List discovered assets + coverage counts |
| GET | /v1/admin/discovery/assets/{id} |
Detail with evidence |
| POST | /v1/admin/discovery/assets/{id}/onboard |
Returns a pre-fill config payload; marks onboarded |
| POST | /v1/admin/discovery/assets/{id}/dismiss |
Mark not-relevant |
| POST | /v1/admin/discovery/reconcile |
Re-run governance matching for all assets |
| GET / POST | /v1/admin/discovery/collector-keys |
Manage collector keys (POST .../{key_id}/revoke to revoke) |
curl -s -X POST http://localhost:5050/v1/admin/discovery/assets/dasset-01K0.../onboard \ -H "Authorization: Bearer $ADMIN_JWT"{ "status": "onboarded", "prefill": { "kind": "mcp_server", "name": "internal-crm-mcp", "base_url": "http://crm-tools.internal:8080" }}Discoveries surface in two places: the AI Asset Registry (the ungoverned list, coverage scorecard, and onboard/dismiss actions — Discovery Integrations is a drill-down from its header) and Mission Control’s Governance tab (shadow-AI signals).
Related
Section titled “Related”- AI Asset Registry — where discoveries land
- Traffic Data Import — the complementary observed plane (vendor-reported usage)
- Register your own MCP server — the onboarding target for a discovered MCP server
