Skip to content

Prompt Injection Defense

Prompt injection happens when untrusted content influences a sensitive tool call. Strahl makes provenance part of the tool-call decision.

Pattern

Give sensitive tools a requires.source that only trusted origins satisfy.

import strahl
from strahl import ALL, Label


@strahl.tool(
    requires=Label(source=ALL, visibility={"public"}),
    produces=Label(source=lambda url: {f"site:{url}"}, visibility={"user"}),
)
def web_fetch(url: str) -> str:
    ...


@strahl.tool(
    requires=Label(source={"user"}, visibility={"user"}),
    produces=Label(source={"payments"}, visibility={"user"}),
)
def pay_invoice(invoice_id: str, amount: float) -> str:
    ...

Content returned by web_fetch carries source={"site:..."}. That source does not satisfy pay_invoice's requires.source={"user"}, so a web page cannot directly authorize the payment tool.

Checking Results

analysis = strahl.analyze(messages)

if analysis.denied:
    for tool_call in analysis.denied_tool_calls:
        print(tool_call.explain())

analysis.raise_if_denied()

Violation.explain() includes the affected sink, the influencing source, the evidence excerpt, and the violated confidentiality or integrity tags.