awesome-ai-prompts

prompt injection defensespec

One prompt from the awesome-ai-prompts catalog, ready to paste into your AI coding agent.

Copy-paste the block below into any AI coding agent to threat-model and harden one attack class: untrusted text that reaches a model context and tries to act as instructions. The heavy format applies when a missed injection can trigger a destructive action or leak data.

Keywords: prompt injection, untrusted text, tool gating, red team, blast radius

Assess `[the feature, agent, or pipeline]` in this repository for prompt
injection. Treat untrusted text in the context as data, and treat every
action the model can take as reachable by whoever wrote that text. Produce a
fix plan and a runnable test suite, not reassurance.

## Define the scope first

Decide these yourself, not by asking the user.

1. **Target surface** - The feature, agent, or pipeline under review, its
   runtime and environment. Where several candidates exist, pick the one with
   tool access and name the rest out of scope.
2. **Untrusted inputs** - Every channel that adds text to the model context:
   user messages, fetched pages, stored documents, tool and API output,
   retrieved chunks, and history written by an earlier turn.
3. **Reachable actions** - The tools and side effects the model can trigger:
   writes, deletes, sends, payments, network egress, secret reads, under the
   caller's real permissions.
4. **Outputs** - The injection-point inventory, the gating design, the fixture
   suite, the blast-radius cut, and the residual-risk register.
5. **Out of scope** - A broad OWASP sweep, dependency and secret scanning, and
   IAM policy changes have their own prompts; stay on this attack class.

## What to produce

1. **Injection-point inventory** - Every path by which untrusted text reaches
   the context, as `file:line` plus the call that adds it. Evidence: a table
   of channel | entry | `file:line` | trust level. No line, no inventory.
2. **Separation design and its limits** - Structured roles, delimiters around
   untrusted spans, provenance tags on every chunk, retrieved content in a
   lower-priority message. Evidence: a `file:line` per technique plus the
   attack it does not stop - no separator is a boundary the model cannot
   cross.
3. **Out-of-band tool gating** - For each reachable action, the check that runs
   in code the model cannot read or edit, against the caller's permissions.
   Evidence: a matrix of action | tool | check | `file:line` | verdict. A
   check the model can talk itself past is not a control.
4. **Output filtering as a second layer** - Refusal strings and pattern
   matching, described after gating. Evidence: the filter rules as `file:line`
   plus which payloads a determined attacker gets past each rule. Never rest a
   blocked-injection claim on the filter alone.
5. **Red-team fixture suite** - Fixtures for direct override, role-play
   framing, instructions hidden in fetched content or metadata, base64 and
   unicode-obfuscated payloads, and injection split across turns. Evidence:
   runnable fixtures in the repo plus a run log.
6. **Blast-radius analysis** - What the model can read (secrets, other tenants'
   rows, admin endpoints) and what it can do. Evidence: a table of exposure |
   current reach | proposed cut | residual.
7. **Residual-risk register** - What stays exploitable after every fix and why,
   the signal that would show it, and the response. Evidence: a risk-ranked
   list; a model that reads text cannot be fully defended.

## Method

Run the phases in order. Each has an exit condition.

1. **Baseline the exposure** - Run any existing suite and log current behavior.
   If none exists, push one payload through the real pipeline. Exit: a logged
   pre-fix baseline.
2. **Trace input to context** - Follow each untrusted channel from entry point
   to the call that appends it, citing a line per hop. Exit: the inventory is
   complete and every row resolves.
3. **Price the separation** - Apply each available technique, then write down
   the attack it does not stop. Exit: every technique pairs a limitation with
   a `file:line`.
4. **Build the fixture suite** - One fixture per pattern, each asserting the
   observable effect: the disallowed call never fires, no secret leaves, the
   task completes. Exit: a run log showing every fixture passing.
5. **Gate the tools** - Move every permission check out of band and verify each
   rejects a call made without the caller's rights. Exit: the gating matrix
   has a verdict and a `file:line` per action.
6. **Cut the blast radius** - Reduce what the model can read and do, then
   re-run the suite to confirm no fixture regressed. Exit: before and after
   run logs.
7. **Re-test and rank** - Re-run the whole suite, then order residual risks by
   likelihood and impact. Exit: a final run log and a signed-off risk register.

## Verification

Before declaring the hardening complete, confirm each of these:

- [ ] Scope names the surface, its runtime and environment, the untrusted
      inputs, the reachable actions, and what is out of scope.
- [ ] Every injection point is a `file:line` plus the call that adds it; no
      inventory row lacks a line.
- [ ] Every separation technique carries a `file:line` and the attack it does
      not stop; none is called a boundary.
- [ ] Every reachable action has an out-of-band check with a `file:line` that
      rejects a call the caller lacks rights for.
- [ ] Each fixture runs from the repo and its run log shows the safe observable
      outcome, not a refusal string.
- [ ] The blast-radius table lists what the model can read and do, each cut,
      and the residual that remains.
- [ ] Residual risks name the signal that would reveal exploitation and the
      planned response.
- [ ] The pre-fix baseline and the post-fix run are both logged, so the change
      is measured rather than asserted.

## Rules

- Never present instruction/data separation, refusal filters, or the system
  prompt as a boundary the model cannot cross.
- Never add a callable tool without its out-of-band check, and never let that
  check live in the model's own reasoning.
- Never accept a refusal string as proof a payload failed; assert on the
  observable effect instead.
- Keep the payload fixtures in the repo so the suite reruns, and never fire
  them at production.
- Report a gap as a gap with severity rather than rounding it up to covered;
  every claim needs a `file:line`, a fixture, or pasted command output.

More security-performance prompts