Skip to main content

OWASP Top-10 for LLM Applications — Yabanin Control Mapping

This page maps the OWASP Top-10 for LLM Applications (2025/2026 list) to the controls that actually exist in the Yabanin codebase — what each control is, how it is enabled, and, honestly, where coverage ends. Every control names its code path or doc; nothing on this page is roadmap dressed up as shipping software (planned items are labeled as such).

Yabanin is a gateway, not an LLM application: most risks below are about what the applications behind the gateway do. The gateway's role is to give the operator enforcement points those applications cannot bypass — policy is admin-owned and org-scoped, never per-request (Policy Pipeline §1).

Status legend: built-in (ships in the code), opt-in (built-in, off by default, enabled by config/policy), author-it (no dedicated control; the operator authors one from pipeline primitives), not covered (no control; named so nobody assumes one exists).

LLM01 — Prompt Injection​

Risk: untrusted input steers the model (directly, or indirectly via tool results and retrieved documents).

ControlStatusWhere
Deterministic injection-phrase detector (RU + EN)built-in, opt-inpkg/guardhooks/finding.go (regex:injection), pipeline step builtin/injection (pipeline.md §5)
Guard modes on egress/tool params: off / log / redact / denybuilt-in, opt-inpkg/guardhooks/hook.go, YABANIN_GUARD_MODE (agent-governance.md)
Custom deny/allow lists per org (contains, regex steps)author-itbuiltin/contains, builtin/regex (RE2, expansion-bomb-safe)
Semantic second opinionauthor-itllm_judge step (pkg/pipeline/llmjudge) — org-authored judge prompts, temperature pinned to 0
External scanner callouts (self-hosted Presidio, Lakera-class)author-itpkg/pipeline/callout — egress allow-list + SSRF guard
Blast-radius reduction: per-agent tool grants, allow-list intersection, args schema/regex guards, result post-checksbuilt-in, opt-inpkg/mcpagg, pkg/toolpolicy (mcp-gateway.md §7, tool-policies.md)
Pipeline self-protection: gateway-made judge calls carry the internal judge=true marker and are exempt; inbound requests presenting X-Yabanin-Judge (any value, even empty or duplicated) are rejected instead of exempted, so a hostile payload cannot trigger recursion; unknown step actions rank as denybuilt-inpipeline.md §6.2, pkg/pipeline/engine.go

Enable: set YABANIN_GUARD_MODE=redact|deny, or attach a policy with builtin/injection on pre_upstream / tool_pre; the deploy/policies/_pack/sovereign-default.yaml pack includes it (ships OFF — pipeline.md §8).

Boundaries (honest): detection is deterministic phrase/regex matching — there is no built-in semantic injection classifier; a judge/callout step is the intended answer. Indirect injection arriving inside tool results is scanned by rule post-checks (secrets/PII/deny_regex), not by semantics. The pre-pipeline posture documented in security-audit.md ("prompt injection is inherent") still holds for deployments that never enable guards.

LLM02 — Sensitive Info Disclosure​

Risk: PII/secrets leak into prompts, responses, logs, or other orgs' hands.

ControlStatusWhere
National PII detectors with checksum validation: RU (INN, SNILS, internal passport, OGRN, phone) + BR/IN/MY/AE/ZA/NG/KE/EG, PAN with Luhnbuilt-in, opt-inpkg/guardhooks/finding.go, pkg/guardhooks/ru_ids.go; pipeline builtin/national-pii
Secret-shape detectors (provider keys, PEM, JWT) + credential-keyed JSON valuesbuilt-in, opt-inpkg/guardhooks/credkeys.go; pipeline builtin/secrets (evidence quoted as [REDACTED_SECRET])
Redaction and reversible pseudonymization ({{YPP_n}} aliases, outbound-only — no reverse substitution into responses)built-in, opt-inbuiltin/redact, builtin/pseudonymize (pipeline.md §5)
Data-boundary routing: rewrite the model to an in-region one when PII is foundbuilt-in, opt-inbuiltin/model-rewrite (pipeline.md §5)
Callout projections bound what leaves the gateway (messages / fields:a,b; metadata never leaves)built-inpkg/pipeline/callout, pipeline.md §6.1
Encryption at rest: enc: AES-256-GCM envelopes, fail-closed writesbuilt-inpkg/encryption, mcp-gateway.md §6
Org isolation: row-level security with app.current_org GUC pinned per transactionbuilt-inpkg/adminstore, pkg/mcpagg (sqlcontract tests)
Masked reads: BYOK keys and MCP credentials read back as last-4 / has_secret only; plaintext never crosses the APIbuilt-inpkg/mcpagg/creds.go, byok.md
Log hygiene: redactPII on event payloads, URL credential stripping, decision log stores content hashes — quoted user content persists only in shadow/debug retentionbuilt-inpkg/eventpublisher/redis_publisher.go, pipeline.md §9

Enable: YABANIN_GUARD_MODE for the always-on path; policies for pseudonymize/mask/deny per org, key-label, model, endpoint.

Boundaries (honest): the offline jurisdiction set is fixed (RU + 9); other jurisdictions need an authored regex step or a callout detector. The guardhooks confidence threshold is 0.9+ (checksum/strict-format), so format-only matches are not redacted. Pseudonymization deliberately never re-substitutes into responses (owner decision) — workflows needing the originals must resolve them out-of-band.

LLM03 — Supply Chain​

Risk: vulnerable dependencies, tampered models, or untrusted components in the serving path.

ControlStatusWhere
govulncheck (symbol-level) in the quality gates + go mod verifybuilt-inmake analyze-security, _quality-security (Makefile), scripts/quality/dep_audit.py
Pinned analyzer/toolchain versions; finding triage scriptbuilt-inmake install-analysis-tools (Makefile), scripts/security/govulncheck-classify.sh
Container hardening: read-only filesystems, no-new-privileges, internal bridge networkbuilt-insecurity-audit.md
Model supply control: model allow-list step + org/model whitelists per key/teambuilt-in, opt-inbuiltin/model-whitelist, pkg/whitelist
Policy/prompt provenance: policies reconcile from git and record the git SHA; judge prompts are versioned resourcesbuilt-inpipeline.md §8, pkg/policystore

Boundaries (honest): scanning covers Go only — the dashboard/site npm tree and Docker base images are not govulnchecked here. There is no SBOM generation or attestation. Models are upstream services: the whitelist constrains which models serve, not the integrity of their weights; a model-provenance scheme is not covered. Callout scanners are third-party services inside the trust boundary once an operator allow-lists them.

LLM04 — Data and Model Poisoning​

Risk: training/fine-tuning data, embeddings, or cached content poisoned to change behavior.

Yabanin operates no fine-tuning or training-data pipeline, so the classic poisoning surface does not exist here; the adjacent surfaces are:

ControlStatusWhere
Per-org cache keying (cache:{org_id}:…) — no cross-org cache reads; semantic layer can be disabled per org (exact/off privacy modes); admin-only toggle with auditbuilt-incache-architecture.md, pkg/cache
Cache precision measured and published, so a semantic near-hit is a documented trade-off rather than a silent behavior changebuilt-incache-precision.md
Immutable policy versions + git reconciliation (a poisoned DB edit shows as DRIFT and is overwritten by git on apply)built-inpipeline.md §8
Versioned judge prompts (judges/<name>@<version>) — a tampered prompt changes the version, not the semantics of existing referencesbuilt-inpkg/pipeline/llmjudge

Boundaries (honest): the ML task classifier (pkg/classifier, make train-classifier) trains on gateway traffic metadata — its training corpus has no provenance/attestation chain. Customer-side vector stores and fine-tuning datasets are entirely outside this codebase.

LLM05 — Improper Output Handling​

Risk: model output passed unchecked into downstream contexts (shells, SQL, browsers, tools).

ControlStatusWhere
Output hooks: post_upstream, stream_prefix, stream_final run the same policy engine over responses and stream aggregatesbuilt-in, opt-inpipeline.md §2, §7
Structured-output checks: JSON Schema / JSON keys validation; code-language detection; URL scheme/host checksbuilt-in, opt-inbuiltin/json-schema, builtin/json-keys, builtin/code-detect, builtin/url-check
Streaming safety: prefix gate checks one captured snapshot before buffered bytes are released; chunk carry applies a replacement learned from a complete prefix match to later occurrences, including split occurrences, but does not guarantee detection of incomplete or later-new valuesbuilt-in, opt-inpipeline.md §7, pkg/pipeline/streaming
Tool-result post-checks (secrets/PII/deny_regex, flag/mask/deny) before an agent sees a tool resultbuilt-in, opt-inpkg/toolpolicy/guard.go, mcp-gateway.md §7

Enable: attach a policy to output hooks; output kinds are the default scope of the JSON-schema step.

Boundaries (honest): the gateway treats output as data — it does not context-encode output for a downstream renderer (HTML/SQL/shell escaping stays the application's job) and does not sandbox what clients do with results. A stream_final deny cannot unsend already-streamed bytes; it degrades to a flagged decision-log record (pipeline.md §7).

LLM06 — Excessive Agency​

Risk: agents take more actions, or more consequential ones, than intended.

ControlStatusWhere
Agent-principal keys (yag_*) — tool calls rejected for non-agent keys; X-Agent-Id stripped on ingress and re-set only from the verified principalbuilt-inpkg/mcpagg/proxy.go, mcp-gateway.md §2
Static least privilege: per-agent grants, effective tool set = server allow-list ∩ grant allow-list; a blocked call is indistinguishable from "server unavailable" (404)built-inpkg/mcpagg/catalog.go, mcp-gateway.md §2
Per-call parameter guards: JSON-Schema on args, max_bytes, deny_regex (pre-egress 400), org deny policies for model-declared tool_callsbuilt-in, opt-inpkg/toolpolicy (tool-policies.md)
Cost/blast-radius ceilings: per-agent daily budgets, per-task token budgets, org RPM/TPM capsbuilt-inpkg/budget/agent.go, agent-governance.md, LLM10 below
Full attribution: every call → request_logs row + hash-chained audit + gateway_mcp_calls_total / OTel spanbuilt-inmcp-gateway.md §2, pkg/auditlog (sha256 chain)
Native MCP endpoint reuses the same invoke guard chain; stateless HMAC-signed sessionsbuilt-inpkg/mcpserver

Boundaries (honest): grants are static enables — there is no per-call human-approval/consent workflow; if an agent should never call a tool unattended, the grant must not exist. Agency limits are only as good as the allow-lists admins configure.

LLM07 — System Prompt Leakage​

Risk: the system prompt (instructions, secrets embedded in it) is revealed through output.

ControlStatusWhere
Secret-shape detectors over responses (post_upstream / stream_final) catch secret-shaped content leaving the modelauthor-itbuiltin/secrets with output kinds
Deny/flag lists of canonical prompt fragmentsauthor-itbuiltin/contains, builtin/regex
Server-side partials: shared prompt fragments live in prompt studio and are substituted server-side, never shipped to clientsbuilt-inpipeline.md §5 (builtin/partials-substitute)

Boundaries (honest): there is no dedicated system-prompt-leakage detector — no classifier for "this text looks like our system prompt". Mitigation must be authored as policies (contains/regex/judge), and none of them can stop a model from paraphrasing its instructions. Keep secrets out of system prompts; the gateway cannot retroactively fix a prompt that contains them.

LLM08 — Vector and Embedding Weaknesses​

Risk: embedding inversion, cross-tenant vector leakage, poisoned retrieval.

Yabanin's embeddings endpoint is a pass-through; the gateway operates no customer vector store. The nearest in-gateway vector surface is the semantic cache:

ControlStatusWhere
Per-org keying of all cache layers — no cross-org semantic hitsbuilt-incache-architecture.md
Org privacy modes: semantic layer switchable to exact or off; exact layer always org-keyedbuilt-incache-architecture.md
Measured precision/recall of the semantic judgment, publishedbuilt-incache-precision.md
Cache policy changes admin-only + audited; TTL + janitor bounds stale entriesbuilt-incache-architecture.md

Boundaries (honest): no embedding-inversion or membership-inference detection exists. Similarity thresholds trade precision for savings; an org whose threat model treats near-duplicate answers as leakage must run the semantic layer off.

LLM09 — Misinformation​

Risk: the model states falsehoods with confidence.

Not covered by dedicated controls. There is no grounding check, factuality scorer, or retrieval-verification in the codebase, and this page refuses to dress one up. What exists is adjacent:

ControlStatusWhere
Org-authored judge steps can score outputs against any rubric, factuality included (deterministic temperature, threshold → deny/flag)author-itpkg/pipeline/llmjudge
Quality sampling (evalgate) measures judged quality per model pair/task class — a measurement, not a preventionbuilt-inevaluation.md, mcp-gateway.md §2
Jurisdictional lineage attestation certifies where a response was processed — provenance of processing, not truth of contentbuilt-inlineage.md

LLM10 — Unbounded Consumption​

Risk: runaway agents, cost bombs, resource exhaustion.

ControlStatusWhere
Org caps: RPM / TPM, split input/output TPM (ITPM/OTPM), per-key TPM; `YABANIN_ORG_CAPS=shadowenforce`, fail-closed on store errors, beta defaults (60 RPM / 200k TPM / $50)built-in
Per-key/team rate limits (YABANIN_KEY_RATE_LIMITS), fair-share priorities on retrybuilt-in, opt-inpkg/gateway/ratelimit.go
Budgets with reservations: team monthly / agent daily hard limits → 429; fail-closed admission (store outage = 503, spend never unbounded); soft limits loggedbuilt-inpkg/budget, security-audit.md, runbooks/budget-reservations-alerts.md
Circuit breakers, per-endpoint or global (YABANIN_CIRCUIT_SCOPE) — a flapping upstream stops consuming spendbuilt-inpkg/circuit, pkg/gateway/circuit_wiring.go
Bounded work everywhere: streaming prefix buffer (64 tokens / 500 ms), bounded MCP proxy timeouts + max response size, callout singleflight + per-step timeouts, regex max_input caps (1 MiB default / 64 MiB hard)built-inpipeline.md, mcp-gateway.md
Loop visibility: gateway_mcp_calls_total, gateway_policy_*, spend analyticsbuilt-inmcp-gateway.md §2, analytics.md

Boundaries (honest): default caps are beta defaults — a deployment that raises them owns the consequences. Rate caps are per-org/per-key, not per-end-user; an org with many humans behind one key needs key-level caps or upstream quotas. Per-provider breaker isolation (one global breaker today) is a known defect tracked for the OUTPLAY routing card (OP-18).

Enabling controls — quick reference​

LayerSwitchDefault
Guard hooks (PII/secrets/injection on chat egress + tool params)YABANIN_GUARD_MODE=log|redact|denyoff
Policy pipelineYABANIN_POLICY_MODE=shadow|enforce + attached policiesoff
Sovereign default pack (PII + secrets + injection)yb policies reconcile --include-pack, lands disabledoff
Tool guardrails on MCP/A2Aorg tool policies + per-server rulesoff (no rules = passthrough)
MCP/A2A/native-MCP surfacesYABANIN_MCP_GATEWAY=1 (+ A2A equivalent)off
Org caps / key limitsYABANIN_ORG_CAPS=enforce / YABANIN_KEY_RATE_LIMITSshadow / off
Callout egressYABANIN_POLICY_CALLOUT_ALLOW_HOSTSempty = callout steps unavailable (fail-closed)
MCP upstream egressYABANIN_MCP_ALLOWED_UPSTREAMSempty = every host rejected (fail-closed)

The default-deny posture of every egress knob is deliberate: with nothing configured, nothing dials out.