Skip to content

Defense in depth for LLM apps

Layer input checks, context construction, model guardrails, output validation, capability limits and monitoring so no single failure is catastrophic: which layers are deterministic, how layers map to attacks, fail-open versus fail-closed, guardrail models and a practical order of work.

14 min·Verified 2026-111 animated diagram+50 XP

No single control stops every attack. Defense in depth stacks independent layers so that when one fails (and each will sometimes fail), another catches the problem. The goal is not a perfect wall but a system where no single failure is catastrophic, and where an attacker must defeat several different kinds of control at once.

Defense in depth: switch layers off and watch what gets through
Interactive
Attack
  1. Input controls · auth, rate and size limitsready
  2. Context building · no secrets, per-user data, untrusted isolatedready
  3. Model guardrails · prompt hardening, safety classifierready
  4. Output validation · schema, escaping, secret scanready
  5. Capability limits · least privilege, confirmation, sandboxready
  6. Monitoring · logs, alerts, kill switch (detects)ready

Deterministic layers (limits, authorisation, validation) are reliable. Probabilistic ones (prompt, classifiers) sometimes fail, which is why you stack them.

#The layers

  1. Input controls. Authentication, rate limits, size limits, file-type checks, and optional injection or abuse classifiers.
  2. Context construction. Include only data the user is authorised to see; delimit untrusted text; keep secrets out.
  3. Model-level guardrails. A well-chosen system prompt, a safety-tuned model, and policy classifiers (for example Llama Guard-style models run locally) to screen prompts and outputs.
  4. Output validation. Schema checks, escaping, URL allowlists, PII and secret scanners.
  5. Capability limits. Least-privilege tools, server-side authorisation, sandboxes, confirmation for consequential actions.
  6. Monitoring and response. Logging of tool calls, anomaly alerts, kill switches, and an incident process.

Each layer in a sentence of detail:

Layer Examples Stops
Input controls API keys, per-key rate limits, max prompt tokens, upload type and size checks Abuse, denial of wallet, oversized or malformed input
Context construction Per-user retrieval filters, no secrets in prompts, untrusted text delimited and labelled Cross-user leakage, secret extraction, some injection
Model guardrails Hardened system prompt, safety classifier on input and output, refusal behaviour Casual misuse, many policy violations
Output validation JSON-schema checks, HTML escaping, link allowlists, secret and PII scanners XSS, exfiltration through links and images, malformed output reaching systems
Capability limits Narrow tools, per-user authorisation, sandbox, confirmation for sends and deletes Damage from a fooled model
Monitoring and response Tool-call logs, alerts, kill switch, runbook Prolonged or unnoticed incidents

#Which layers are deterministic?

Layer Deterministic? Reliability
Auth, rate limits, size limits Yes High
Server-side authorisation of tools and data Yes High
Schema validation, escaping, allowlists Yes High
Sandboxing Yes High
System prompt No Low to medium
Safety classifiers No (probabilistic) Medium
Model alignment No Medium
Monitoring Detects, does not prevent Depends on alerts being acted on

Put your trust in the deterministic layers and treat probabilistic ones as a way to reduce volume and add friction. A useful test of any control: would it still work if the model were fully controlled by the attacker? If yes, it is a real boundary. If no, it is a speed bump.

#Why layers multiply, and when they do not

If three layers each independently stop 90 percent of attempts, the chance an attempt passes all three is 0.1 × 0.1 × 0.1 = 0.1%. That is the Swiss-cheese idea: holes rarely line up.

The catch is independence. Two layers that fail for the same reason (both are prompts, both are the same classifier family, both rely on the model noticing something) fail together. A hardened system prompt plus a prompt-based guard model that uses the same base model are highly correlated. Mix different kinds of controls: a deterministic permission check, a schema validator, a rate limit and a classifier fail in unrelated ways.

#Mapping attacks to layers

Use a table like this in your design review. It shows which attacks have only one layer of protection (a red flag):

Attack Input Context Guardrails Output Capability Monitoring
Giant prompt / cost attack ✓ ✓
"Print your system prompt" ✓ (no secrets) ✓ ✓ (scan) ✓
Hidden instruction in a document ✓ (isolate) ✓ ✓ (no tools) ✓
"Delete all records" via tool ✓ ✓ (authorise, confirm) ✓
Script tag in output (XSS) ✓ (escape)
Cross-tenant data access ✓ (filter) ✓ (authorise) ✓

Rows with a single tick need another layer. Try it live in the diagram above: switch layers off and see which attacks get through.

#Guardrail models

Open classifier models can screen both inputs and outputs for categories such as violence, self-harm, illegal activity and prompt-injection patterns. They:

  • add latency and cost (an extra model call),
  • produce false positives (blocking legitimate users) and false negatives,
  • need evaluating on your traffic, since categories and tone differ by domain,
  • are themselves attackable (an injection that targets the classifier).

Tips: run them in parallel with the main call where possible, use a small fast model, tune thresholds with data, log what they block, and treat them as one layer among several. For structured, narrow apps, rules and schemas often beat classifiers: if the output must be one of five labels, enforce that with a grammar and skip the classifier (structured output).

#Fail safely

Decide what happens when a layer fails or is unavailable:

Risk of the feature Policy when a safety layer is down
High (payments, deletion, external messages, medical or legal output) Fail closed: refuse or route to human review
Medium (internal summaries with private data) Fail closed for sensitive data; degrade to a restricted mode
Low (public FAQ answers) Fail open with a notice, and alert

Write the decision down per layer. The worst outcome is the accidental one: a classifier timeout silently returning "safe".

#Kill switches

Every feature with side effects needs a way to turn it off fast: a feature flag that disables a tool, a switch that forces confirmation for all actions, a way to revoke a model release. Test the switch before you need it, and make sure on-call knows where it is (reliability patterns).

#Security testing as a layer

Include adversarial test cases (injection, leakage, abuse) in your release evaluations, track the success rate over time, and re-run them whenever the model, prompt or tools change. Test layers individually (does the output scanner catch a planted canary? does the authoriser reject a cross-user ID?) and together (what is the end-to-end attack success rate?). The red-team lab builds a small harness, and CI shows how to run it on every change.

#A worked example: a support assistant

Concern Layer and control
Anonymous users burning GPU Input: auth, per-key limits, max tokens
One customer reading another's data Context: per-customer retrieval filter. Capability: tools take identity from the session
Hidden instructions in uploaded PDFs Context: PDFs processed in a tool-less call, validated summary passed on
Model leaks an internal code Context: no secrets in the prompt. Output: scan for the canary
Phishing link in a reply Output: link allowlist, markdown sanitiser
Refund abuse Capability: refund tool creates a pending request, amount cap in code, human approval above threshold
Unnoticed attack Monitoring: tool-call logs, alert on refund-request spikes, kill switch for the refund tool

Seven concerns, each with a primary deterministic control, and probabilistic layers on top.

#Practical order of work

  1. Remove secrets from prompts and set up authorisation on tools and data (largest risk reduction)
  2. Limit tools and add confirmations
  3. Validate and escape output
  4. Add rate limits and size caps
  5. Add monitoring and logging with redaction
  6. Add classifiers and prompt hardening on top

Items 1 to 4 are mostly ordinary engineering and give most of the protection. Items 5 and 6 add detection and polish.

#Common mistakes

  1. Counting probabilistic layers as boundaries.
  2. Stacking correlated layers (three prompts, one model) and calling it depth.
  3. A guardrail with no false-positive measurement, which annoys users into disabling it.
  4. No kill switch.
  5. Defending only the input, ignoring outputs and tools.
  6. No tests, so layers silently decay as prompts and models change.

#Exercise

An internal assistant summarises uploaded contracts and can email the summary to colleagues. Today the only defence is a system prompt saying "never send confidential data outside the company".

  1. Which kind of control is that, and how reliable?
  2. Propose four layered controls.

Answers:

  1. A probabilistic, model-level control: low to medium reliability, and it can be bypassed by an instruction hidden in a contract.
  2. (a) Capability: restrict recipients to company-domain addresses in code and require confirmation showing recipient and body. (b) Context: process contracts in a tool-less call producing a schema-validated summary. (c) Output: scan the summary for secrets and external URLs. (d) Monitoring: log every send, alert on unusual volume or new recipients, and provide a kill switch for the email tool.

Quick quiz

+10 XP per correct answer, +25 XP for a perfect score

  1. 1. Why use several defensive layers?

  2. 2. Which layer remains effective even when the model is completely fooled?

  3. 3. Three layers each stop 90% of a given attack, independently. What fraction gets through all three?

  4. 4. A guardrail classifier is unavailable. For a feature that can send money, what should happen?

  5. 5. Which is the most valuable first step for a new LLM app?