Home

/

Prompt Injection: Blast Radius

/

Action Schema and Policy Reference

Action Schema and Policy Reference

Appendix B
Appendix
4
min read

Provenance

public enum Provenance { Trusted, Tainted }
ValueMeaning
TrustedOriginated inside your boundary: system prompt, configuration, a value an authenticated user typed into a field you control, a row your own code wrote after a successful action
TaintedEverything else, including anything of unknown origin

Join rule: any tainted input makes the result tainted. No operation converts tainted back to trusted. A function claiming to do so is a classifier, and chapter 4 covers why that is not a boundary.

public readonly record struct Tagged<T>(T Value, Provenance Origin);
FieldNotes
ValueThe value itself
OriginSurvives storage as a persisted column (ch 12), crosses process boundaries explicitly, defaults to Tainted when unknown

Tool registration

public sealed record ToolPolicy(
    string ToolName,
    Capability RequiredCapability,
    bool Irreversible,
    bool ExternallyVisible,
    bool CrossesTrustBoundary,
    ProvenanceRule ArgumentRule);
FieldRequiredNotes
ToolNameyesMust match the registered function name exactly
RequiredCapabilityyesChecked against the caller's set; see below
IrreversibleyesNo default. Does an inverse operation exist, and can you reach it inside the window that matters? Ask your retention configuration, not your intuition
ExternallyVisibleyesCan anything outside the boundary observe that this happened
CrossesTrustBoundaryyesDoes data move from private to less-private
ArgumentRuleyesHow argument provenance affects the verdict

A tool is consequential if any of Irreversible, ExternallyVisible or CrossesTrustBoundary is true. That is chapter 5's definition, mechanised.

Make all six fields required. An optional field acquires a default, the default is permissive, and a tool gets added on a Friday without anyone answering the question.

ProvenanceRule

ValueEffect
AllowAnyProvenance is not considered. Only for tools with no consequential flag set
DenyTaintedAny tainted argument denies the call
EscalateTaintedAny tainted argument routes to a human (ch 14)
DenyTaintedIn(params string[])Applies to named arguments only, for tools where one field matters and others do not

The common configuration for an irreversible tool is EscalateTainted. DenyTainted where no reviewer has the context to judge.

Capabilities

public sealed record Capability(
    string Operation,
    string Resource,
    DateTimeOffset Expires,
    string TaskId);
FieldNotes
OperationA verb: read, send, refund, delete
ResourceWhere the reduction comes from. order:88431, not order:*. Two-stage issuance where the specific resource is not known at task start
ExpiresSet from the task, not a global default. Seconds to minutes. Anything in days is a service account
TaskIdMakes the audit trail readable months later
public sealed record CapabilitySet(IReadOnlyList<Capability> Items)
{
    public bool Covers(Capability required) =>
        Items.Any(c => c.Operation == required.Operation
                    && c.Resource == required.Resource
                    && c.Expires > DateTimeOffset.UtcNow);
}

Capabilities are derived from the authenticated user's authority at task start, never from a service account, and never widened by anything the model says. Task intent is declared in code, not inferred.

Proposals and verdicts

public sealed record Proposal(
    string ToolName,
    IReadOnlyList<Argument> Arguments,
    CapabilitySet Held);

public sealed record Argument(string Name, object? Value, Provenance Origin);

public enum Outcome { Allow, Deny, Escalate }

public sealed record Verdict(
    Outcome Outcome,
    string DeniedBy,
    string ReasonForModel,
    string ReasonForAudit);
FieldNotes
DeniedByNames the mechanism: default-deny, capability, tainted-irreversible, egress-policy, budget-exhausted, policy-unavailable, human-rejected. Never null on a non-allow verdict
ReasonForModelGoes back into the conversation. Deliberately uninformative. "That action is not available." A detailed denial is a free probe of your policy
ReasonForAuditGoes to the log only. The sentence you want during an incident review

Evaluation order

Fixed, and the order matters.

public Verdict Evaluate(Proposal p)
{
    if (!_policies.TryGetValue(p.ToolName, out var rule))
        return Verdict.Deny("default-deny", "That action is not available.");

    if (!p.Held.Covers(rule.RequiredCapability))
        return Verdict.Deny("capability", "That action is not available.");

    if (rule.Irreversible && p.Arguments.Any(a => a.Origin is Provenance.Tainted))
        return Verdict.Escalate("tainted-irreversible", "This needs confirmation.");

    return Verdict.Allow();
}
  1. Existence. A tool with no policy is denied. Default-deny is what makes the design survive a team that adds tools faster than policies.
  2. Authority. Capability check. Cheap and it fails most misconfigurations.
  3. Provenance. The check no conventional authorisation system can make.

Fail closed. If the policy store cannot be reached, deny. An agent that stops working is an incident; an agent that keeps working is a breach discovered later by someone else.

Egress policy

public bool IsAllowed(string url, Provenance origin)
{
    if (!Uri.TryCreate(url, UriKind.Absolute, out var uri)) return false;
    if (uri.Scheme is not ("https" or "mailto")) return false;
    if (!_allowedHosts.Contains(uri.Host)) return false;
    if (origin is Provenance.Tainted && uri.Query.Length > 0) return false;
    return true;
}
RuleWhy
Scheme allowlistdata:, file: and custom schemes are channels
Host allowlistDestinations come from configuration, never from the model
No tainted query stringsCloses reflection through a permitted host without having to enumerate which permitted hosts are safe

Images in rendered output are stripped unconditionally. Where a product needs them, fetch server-side after checking the URL, and serve from your own host.

Audit record

public sealed record GateRecord(
    DateTimeOffset At,
    string SessionId,
    string TaskId,
    string ToolName,
    IReadOnlyList<(string Name, Provenance Origin, string SourceRef)> Arguments,
    Outcome Outcome,
    string DeniedBy,
    string ReasonForAudit);

Argument origins are recorded. Argument values are not. Logging values recreates the exposure chapters 6 and 10 exist to prevent, and makes the log store the thing an attacker wanted.

SourceRef points at the document, ticket or memory record that produced each tainted argument. It is what turns chapter 17's blast-radius assessment into a query.

Record denied and escalated proposals as well as allowed ones. The denials are the pattern, and a system that never reads its denial log has discarded its only signal about how often it is being probed.

the-three-year-bug
why-the-industry-shipped-anyway
injection-is-not-jailbreaking
why-the-confusion-persists
the-lethal-trifecta
running-the-audit
why-filtering-fails
measured-here-on-a-named-model
why-this-is-structural
what-solved-would-look-like
the-harness
provenance-every-value-knows-where-it-came-from
on-the-reference-agent
quarantine-the-planner-never-reads-the-mail
what-two-models-cost-in-practice
capability-authority-the-agent-cannot-widen
expiry-is-a-feature
the-gate-the-model-proposes-code-disposes
the-policy
failing-closed
egress-closing-the-exfiltration-leg
how-much-can-actually-leak
sandboxing-containing-the-code-the-agent-writes
the-sandbox-held-and-it-did-not-help
poisoned-memory-poisoned-retrieval
cleaning-up-afterwards
the-tool-supply-chain
mcp-and-the-rest
human-in-the-loop-that-isnt-theatre
when-there-is-nobody-there
testing-for-injection
measuring-coverage-not-pass-rate
red-teaming-agents
a-finding-worked-through
when-it-happens-anyway
what-the-logs-cost-you-in-an-incident-you-did-not-have
governance-procurement-and-the-regulator
writing-the-policy
end-to-end
what-it-actually-took
what-stays-broken
why-this-is-probably-structural
the-trifecta-audit-worksheet
action-schema-and-policy-reference
control-mapping
prompt-injection-sources
incidents
appendix-e-what-we-re-ran-ourselves
e4-the-control-that-keeps-e2-and-e3-honest

Download the full PDF for free?

Free download — no account required

Get the PDF
Get the PDF
Related Chapters
Free Download
Get the full PDF
All pages, including all code examples, diagrams, and the appendix reference card.
No spam. Unsubscribe at any time.
Your email won't be shared.
Oops! There's a problem with your request. We're working on fixing it. Please try again later.