OWASP Top 10 for Agentic Applications — control mapping
The OWASP Top 10 for Agentic Applications (ASI01–ASI10, published 9 December 2025) is the vocabulary enterprise agent programmes are now written against. NIST's NCCoE published a concept paper on agent identity in February 2026, and COSAiS is developing SP 800-53 overlays on the same ground.
This page maps the identifiers to what searchcode actually does. Every row names the behaviour and where to verify it, because a control mapping that cannot be checked is marketing.
Four are directly load-bearing for a code intelligence MCP server.
ASI02 — Tool Misuse
Tool misuse succeeds when authorisation is checked only at the agent, not at the tool.
What searchcode does: the same authorisation filter is enforced at every surface — search, the file view, blame, history, the repository list, autocomplete, the HTTP API, MCP tool calls, analytics and every aggregate — and all of them derive it from one function. Not "something similar": the same one.
Three properties make that structural rather than a promise:
- An MCP tool call is the REST call. The tool layer builds the request the router would have matched and runs it through the same middleware chain — same principal, same authoriser, same rate limit, same audit record. There is no second query path for an agent to reach.
- Filtering happens at query time, never after. The authoriser returns the set of repositories the query carries, so a repository the caller may not see is never read. Post-filtering leaks result counts and response timings; both are tested against.
- The zero value denies. An empty repository set grants nothing and
authz.defaultAccessdefaults todeny, so a forgotten assignment fails closed rather than open.
Verify it: /api/v1/explain-access answers "why can Bob see this
repository?" with the binding that granted it, and the same answer is available
as an admin screen. Every denial is audited with outcome: denied.
ASI03 — Identity & Privilege Abuse
Agents inheriting borrowed human sessions and high-privilege credentials.
What searchcode does: there is no deployment-wide MCP key. Every agent call carries a credential that resolves to a real principal, and authorisation is evaluated per call against that principal's groups, capped at what the delegating user has.
Credentials are issued per (user, client) — named at creation, individually
revocable, with last-used tracking — which is what lets an audit record name
which agent acted rather than only which person. An unnamed key is refused by
default (api.apiKeys.requireName), because an unnamed credential is
unauditable.
Two things this page will not claim:
- Static keys are not invalidated by an identity provider disable. The product does not poll a directory and deliberately does not. What is true is written out in full under questionnaire.md#offboarding, and it has three parts, one of which is a manual step.
- Not "competitors ship one shared key". Several scope agent credentials per user already. The distinction worth making is narrower and holds: per (user, client), named and individually revocable, so the audit trail can name the agent.
Verify it: /account lists a user's credentials with last-used times; the
admin credentials view lists any user's. Both revoke in place — the revoke and
the next verification are the same process touching the same map, so revocation
is immediate rather than eventually consistent.
ASI04 — Agentic Supply Chain
The MCP servers your agent depends on are attack surfaces you do not directly control.
A SaaS code-context MCP server is the ASI04 risk: your source code, indexed by a third party, reachable by their staff, with an availability and a breach profile you cannot audit.
What searchcode does: it is self-hosted — it runs on your hardware, with no vendor-operated component anywhere in the request path. The process never phones home: no telemetry, no licence check-in, no analytics, no update ping, on any tier, for any reason. Beyond that it makes no outbound connections at all unless you enable OTLP tracing to your own collector.
- The proof is generated from your own config. The Helm chart renders a NetworkPolicy whose egress rules are derived from the repository URLs you declared and the collector you named, permitting nothing else. Render it against two values files and the rules differ.
- Images are signed with cosign, keylessly, and run as uid 65532 on a read-only root filesystem with all capabilities dropped.
- An SBOM ships with every release — CycloneDX, generated from the built binary rather than from the module graph, so it lists what the linker actually included.
- Licence verification is offline, against a compiled-in public key. There is no activation, no seat check-in and no renewal ping.
Verify it: run it with --network none and a pre-seeded data directory.
Search, the file view, the API, MCP and the API reference all answer. See
Air-gapped install.
ASI10 — Rogue Agents
Compromised or misbehaving agent credentials.
What searchcode does: per-credential rate limiting with anomaly detection against each key's own rolling baseline rather than a global threshold.
api:
apiKeys:
rateLimit:
requestsPerMinute: 5000
anomalyMultiplier: 10
window: 1m
A key that suddenly enumerates the whole estate looks nothing like itself. A global threshold has to be set for the busiest credential and therefore never fires for any of the others, which is why the baseline is per credential.
Verify it: the counters are on /metrics and the usage panel; a credential
exceeding its own baseline produces an audit record and a log line with a unique
code.
The three questions at every trust boundary
OWASP-aligned reviews ask the same three things everywhere: who is acting, what are they authorised to do, and can we prove it later. They map one-to-one:
| Question | Mechanism |
|---|---|
| Who is acting | Proxy-supplied group identity, or a local account, or a named service account. Never an anonymous shared key. |
| What are they authorised to do | Declarative bindings, evaluated by one function at query time, allow-only and order-independent |
| Can we prove it later | An audit log that records denials as well as grants, unconditional on every tier |
That last one is worth stating on its own. Auditing is unconditional and there
is no configuration that turns it off — no licence check, no enabled flag, no
output value that opens a discarding sink. That is a security property rather
than a pricing one: a gated audit log means a licence lapse silently stops
recording security events.
What is configurable is audit.logSearchQueries and the retention window,
because those are privacy and storage decisions you own.
The other six
ASI01, ASI05–ASI09 concern agent planning, memory, reasoning and orchestration — properties of the agent, which in this architecture is your agent in your developer's editor. searchcode ships no model, no chat endpoint and no inference dependency; it is a tool server, and the agent lives in the client where the context is.
That reduces this product's exposure to those six to the surface they reach it through, which is covered by ASI02 and ASI03 above.
Related reading
- Security questionnaire — the security questionnaire answers
- Trust — the posture in one page
- Which credential do I use? — which credential to issue, and why
- Air-gapped install — proving the egress claim