Security: injection, leakage and sandboxing
The model reads everything and believes most of it; the systems around it must not.
Every previous security model you know assumes code and data are separable — you sanitise inputs so data cannot become instructions. A language model dissolves that boundary by construction: everything in the context window is just tokens, and the model’s only skill is continuing them plausibly. That single fact creates a new attack class, and it is not a curiosity — it is the central security fact of building with LLMs.
Prompt injection, direct and indirect
Direct injection is the user typing “ignore your instructions and…” — annoying, mostly a content-policy problem. Indirect injection is the dangerous one: instructions hiding in content the system fetches on its own — a web page the agent browses, a résumé the screener summarises, an email the assistant reads — white text on white background works fine, because the model reads everything and privileges none of it. Your parser never executed the attacker’s code; your reasoner did. Delimiters and “treat the following as data” markers raise the bar and reliably fail against adversaries — after years of attempts, there is no known robust defence at the prompt layer alone. Security here is an architecture property, not a phrasing property.
The lethal trifecta
The framing worth memorising from this chapter’s reading: real damage requires three ingredients together — access to private data, exposure to untrusted content, and an exfiltration path (a tool that sends, posts, or even renders a markdown image whose URL leaks data to an attacker’s server). Remove any one leg and injection degrades from breach to nuisance. That is the design method: enumerate the three legs for every AI feature, and break the cheapest one. A summariser with no tools has no third leg. An agent with the user’s inbox and web browsing and send-email has all three, and needs the full treatment below.
The full treatment
- Least privilege, taken literally: the model’s credentials are not your credentials — scoped tokens, allow-listed tools, read-mostly defaults, per-session identity so audit logs mean something.
- Gate by blast radius: reads flow freely; sends, spends and deletes get confirmation, and confirmation UIs must show what will happen (the full recipient list, the actual command), not a vibe.
- Sandbox execution: code interpreters and browsers run in disposable, network-restricted environments — assume hostile output, because sometimes it is.
- Treat output as attack surface too: model output rendered as HTML, executed as SQL, or clicked as links is injection’s second act — sanitise it like any untrusted input, because that is what it is.
- Mind the exhaust: prompts and outputs land in logs, caches, traces and eval sets — private data now lives in your observability stack, with its own audience and retention rules.