Threat-model the LLM feature, not the model card

STRIDE still works when a language model sits in the middle — if you treat the model as an untrusted component.

Marcos MartínMarcos Martín
Defense layers in an LLM request pipeline

Teams shipping a chatbot often start from the vendor’s model card: training data, eval scores, “we do not store prompts.” That is useful procurement language. It is not a threat model of your feature. The feature is: a user (or another service) sends text, you retrieve context, you call a model, you maybe invoke a tool, you write something back into a ticket, a wiki, or a database.

I threat-model that the same way I threat-model any other service: STRIDE on the data flow, then decide which steps may be automated and which need a human gate. CTMP for the method; CAISP for the LLM-specific failure modes (prompt injection, RAG poisoning, tool abuse). The model is a component you do not fully control — closer to an untrusted parser than to a trusted employee.

A small STRIDE map

STRIDEWhere it shows up in an LLM feature
SpoofingActing as another user, another system prompt, or another tool’s identity.
TamperingRetrieved documents, conversation history, or tool arguments the model did not intend.
RepudiationNo durable log of prompt, retrieval set, model, and tool calls.
Information disclosurePII and secrets in prompts or in what the model echoes outbound.
Denial of serviceUnbounded context, recursive tool loops, cost blow-ups.
Elevation of privilegeA tool allowlist that is really “the model may call anything the API key can.”

None of that requires a new framework. It requires a diagram (who talks to whom), a list of trust boundaries, and mitigations you can actually operate: authn in front of the proxy, DLP on the wire, allowlists for tools, evals in CI, logs you can query.

The human gate is the same idea as a Vault ceremony

At Swisscom I automated a lot of secrets operations. I did not automate the last step of a rekey. PIN, passphrase, quit — those stay human. LLM features have the same shape. Drafting a STRIDE list from a diagram is a good job for a model. Accepting a mitigation as done is not. The pipeline I built for threat modeling (diagrams in, STRIDE threats and mitigations out) is only useful if a person signs the output.

Policy-as-code is how you scale the rest: the rule that “this tool is not callable from this app” should run on every request, not in a reviewer’s head. Same habit as OPA on a merge request, applied to tool calls instead of :latest tags.

What I am not claiming

A STRIDE session is not a red-team engagement. Regex plus a classifier will not catch every injection. A model card is not an SBOM. The useful claim is smaller: if the LLM is just another component in the SDLC, it gets the same treatment as the rest of the factory — a diagram, a control on the wire, a test you can rerun, and a human on the few steps that must never be casual.

Related: security as a Base URL · evals instead of a chat screenshot.