| name | agent-security-bypass-modes |
| description | Prevents agent safety controls from being silently bypassed via artifact serving, guardrail provider errors, or injected instructions in tool results. TRIGGER when: serving files or artifacts generated by an agent, configuring guardrails or content filters for tool calls, ingesting web search results or file content into agent message history, reviewing security posture of a production agent deployment. |
Key Decisions
-
Serve all active web content artifacts (HTML, XHTML, SVG) generated by the agent as Content-Disposition: attachment, never inline. An agent generating HTML can produce scripts that execute in the application's origin if the file is served inline in a browser — either accidentally or as the result of a successful prompt injection. Forcing download moves execution outside the application's origin regardless of content.
-
Configure guardrail middleware to fail closed — block the protected action on provider error, not allow it through. When the guardrail provider (an external API or classifier) fails or is unreachable, an open-default configuration silently allows all tool calls through for the duration of the outage. The downside of false positives during an outage is recoverable; the downside of a silent bypass is not.
-
Normalize and sanitize external content (web search results, file contents, tool outputs) before appending it to the message history. Content from external sources can contain embedded instructions that the model will follow. When the agent also has memory persistence, a successful injection in one session may persist as a long-term fact and affect every future session. Stripping or escaping instruction-like markup before it enters the history breaks the injection chain before it reaches the model.
Anti-patterns
-
What: Serving agent-generated HTML or SVG files inline from the same origin as the application.
Why: The agent may produce HTML with JavaScript — intentionally or as the result of a malicious instruction embedded in prior input — and inline serving executes those scripts with the application's cookies and localStorage.
Symptom: Agent-generated HTML files that contain scripts run in the browser at the application's origin; cross-origin attacks or session hijacking become possible through normal agent usage.
-
What: Defaulting guardrails to fail-open when the guardrail provider is unavailable.
Why: Provider unavailability (network error, timeout, rate limit exhaustion) is treated identically to "allowed"; all tool calls that should be checked proceed unchecked for the outage duration.
Symptom: A guardrail provider outage is invisible to operators and users; restricted tool calls execute freely during the outage and the bypass is discovered only during post-incident review.
-
What: Appending raw tool results (web search snippets, uploaded file contents, MCP outputs) directly to message history without sanitization.
Why: External content frequently contains text formatted to look like instructions; the model treats embedded directives as authoritative.
Symptom: Agent behavior changes unexpectedly after processing certain web pages or files; in the worst case, injected instructions persist to long-term memory and affect every future session for all users.
Structural Template
# Artifact serving: force download for active web content
function serve_artifact(file_path, content_type):
ACTIVE_WEB_TYPES = {"text/html", "application/xhtml+xml", "image/svg+xml"}
headers = {}
if content_type in ACTIVE_WEB_TYPES:
headers["Content-Disposition"] = "attachment"
return serve_file(file_path, headers)
# Guardrail middleware: fail closed by default
class GuardrailMiddleware:
def __init__(self, fail_closed=True):
self.fail_closed = fail_closed
def check(self, tool_call):
try:
result = self.provider.evaluate(tool_call)
if result.blocked:
raise ToolCallBlocked(result.reason)
except ProviderError:
if self.fail_closed:
raise ToolCallBlocked("guardrail provider unavailable — blocked by default")
# fail_open path: allow through — not recommended for production
# External content normalization before history injection
function normalize_external_content(raw_content):
sanitized = strip_xml_instruction_tags(raw_content)
sanitized = escape_role_label_patterns(sanitized)
sanitized = remove_prompt_injection_markers(sanitized)
return wrap_as_tool_output(sanitized) # context signals this is external data