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.