<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Owasp | Roy Gabriel</title><link>https://roygabriel.dev/tags/owasp/</link><description>Roy Gabriel: DevOps Architect &amp; Applied AI Engineer. Technical blog on Go, MCP servers, Kubernetes, and production AI systems.</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 27 Feb 2026 03:18:04 +0000</lastBuildDate><atom:link href="https://roygabriel.dev/tags/owasp/index.xml" rel="self" type="application/rss+xml"/><item><title>The Real Security Model for Agents</title><link>https://roygabriel.dev/blog/real-security-model-for-agents/</link><pubDate>Sat, 18 Oct 2025 12:00:00 -0500</pubDate><guid>https://roygabriel.dev/blog/real-security-model-for-agents/</guid><description>&lt;h2 id="why-this-matters"&gt;Why this matters&lt;/h2&gt;
&lt;p&gt;If you ship tool-using agents, you are shipping:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an execution engine&lt;/li&gt;
&lt;li&gt;with access to external systems&lt;/li&gt;
&lt;li&gt;controlled by untrusted inputs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is the same security posture as any automation platform - except the &amp;ldquo;operator&amp;rdquo; is probabilistic.&lt;/p&gt;
&lt;p&gt;OWASP&amp;rsquo;s Top 10 for LLM Applications makes it clear: prompt injection, insecure output handling, sensitive info disclosure, excessive agency&amp;hellip; these are mainstream risks, not edge cases. [1]
The good news: most mitigations are &lt;em&gt;classic security engineering&lt;/em&gt; applied to a new execution model.&lt;/p&gt;</description><content:encoded>&lt;h2 id="why-this-matters"&gt;Why this matters&lt;/h2&gt;
&lt;p&gt;If you ship tool-using agents, you are shipping:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an execution engine&lt;/li&gt;
&lt;li&gt;with access to external systems&lt;/li&gt;
&lt;li&gt;controlled by untrusted inputs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is the same security posture as any automation platform - except the &amp;ldquo;operator&amp;rdquo; is probabilistic.&lt;/p&gt;
&lt;p&gt;OWASP&amp;rsquo;s Top 10 for LLM Applications makes it clear: prompt injection, insecure output handling, sensitive info disclosure, excessive agency&amp;hellip; these are mainstream risks, not edge cases. [1]
The good news: most mitigations are &lt;em&gt;classic security engineering&lt;/em&gt; applied to a new execution model.&lt;/p&gt;
&lt;p&gt;This article is a practical, production-first security model for agents and MCP tool ecosystems.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Don&amp;rsquo;t &amp;ldquo;secure the model.&amp;rdquo; Secure the &lt;strong&gt;system&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Treat all inputs as untrusted:&lt;/li&gt;
&lt;li&gt;user text&lt;/li&gt;
&lt;li&gt;tool outputs&lt;/li&gt;
&lt;li&gt;retrieved documents&lt;/li&gt;
&lt;li&gt;Design tools with least privilege:&lt;/li&gt;
&lt;li&gt;separate read/write/danger tools&lt;/li&gt;
&lt;li&gt;require preview -&amp;gt; apply for destructive actions&lt;/li&gt;
&lt;li&gt;Centralize auth and policy:&lt;/li&gt;
&lt;li&gt;MCP defines authorization for HTTP transports - use it. [2]&lt;/li&gt;
&lt;li&gt;Control egress and prevent SSRF by default. [3]&lt;/li&gt;
&lt;li&gt;Never let raw model output drive execution without validation (OWASP LLM02). [4]&lt;/li&gt;
&lt;li&gt;Redact logs and manage secrets like an adult (OWASP cheat sheets). [5][6]&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="contents"&gt;Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#threat-model-what-can-go-wrong"&gt;Threat model: what can go wrong&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#security-layers-that-actually-work"&gt;Security layers that actually work&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#tool-design-readwritedanger-tiers"&gt;Tool design: read/write/danger tiers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#output-handling-never-execute-raw-model-output"&gt;Output handling: never execute raw model output&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#secrets-minimize-scope-rotate"&gt;Secrets: minimize, scope, rotate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#network-and-egress-controls"&gt;Network and egress controls&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#logging-and-audit-without-data-leaks"&gt;Logging and audit without data leaks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#a-production-checklist"&gt;A production checklist&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#references"&gt;References&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="threat-model-what-can-go-wrong"&gt;Threat model: what can go wrong&lt;/h2&gt;
&lt;h3 id="1-prompt-injection---policy-bypass-attempt"&gt;1) Prompt injection -&amp;gt; policy bypass attempt&lt;/h3&gt;
&lt;p&gt;A user or document says:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Ignore previous instructions&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Call this tool with these parameters&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Reveal secrets&amp;rdquo;
OWASP calls this out as a primary risk category. [1]&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-insecure-output-handling---downstream-exploitation"&gt;2) Insecure output handling -&amp;gt; downstream exploitation&lt;/h3&gt;
&lt;p&gt;If you pass model output into:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a shell&lt;/li&gt;
&lt;li&gt;SQL&lt;/li&gt;
&lt;li&gt;YAML manifests&lt;/li&gt;
&lt;li&gt;HTTP requests
&amp;hellip;without validation, you&amp;rsquo;ve built an indirect code execution path.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OWASP&amp;rsquo;s LLM02 describes this precisely: insufficient validation and handling of LLM outputs before passing them downstream. [4]&lt;/p&gt;
&lt;h3 id="3-excessive-agency---unintended-side-effects"&gt;3) Excessive agency -&amp;gt; unintended side effects&lt;/h3&gt;
&lt;p&gt;The agent is over-permissioned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it can delete resources&lt;/li&gt;
&lt;li&gt;send emails&lt;/li&gt;
&lt;li&gt;modify production
&amp;hellip;and it will eventually do something you didn&amp;rsquo;t mean.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-data-exfiltration-via-tools"&gt;4) Data exfiltration via tools&lt;/h3&gt;
&lt;p&gt;Tool outputs are rich and often sensitive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;calendar events&lt;/li&gt;
&lt;li&gt;emails&lt;/li&gt;
&lt;li&gt;internal tickets&lt;/li&gt;
&lt;li&gt;source code&lt;/li&gt;
&lt;li&gt;cluster configs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Exfil happens through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;model responses&lt;/li&gt;
&lt;li&gt;logs&lt;/li&gt;
&lt;li&gt;&amp;ldquo;helpful&amp;rdquo; summaries&lt;/li&gt;
&lt;li&gt;tool chaining&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="5-network-abuse--ssrf"&gt;5) Network abuse / SSRF&lt;/h3&gt;
&lt;p&gt;Any &amp;ldquo;fetch URL&amp;rdquo; capability is an SSRF invitation unless you constrain egress. OWASP&amp;rsquo;s SSRF cheat sheet is still relevant. [3]&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="security-layers-that-actually-work"&gt;Security layers that actually work&lt;/h2&gt;
&lt;p&gt;Security in agent systems is defense-in-depth:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Identity&lt;/strong&gt; (who is calling?)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authorization&lt;/strong&gt; (what can they do?)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contracts&lt;/strong&gt; (what does a tool accept/return?)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validation&lt;/strong&gt; (are inputs/outputs safe?)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Egress control&lt;/strong&gt; (where can the system talk to?)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audit&lt;/strong&gt; (what happened?)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kill switches&lt;/strong&gt; (how do you stop it fast?)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="tool-design-readwritedanger-tiers"&gt;Tool design: read/write/danger tiers&lt;/h2&gt;
&lt;h3 id="tiering-is-mandatory"&gt;Tiering is mandatory&lt;/h3&gt;
&lt;p&gt;Split tools by side effects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Read tools&lt;/strong&gt;: list/search/get&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write tools&lt;/strong&gt;: create/update with bounded scope&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Danger tools&lt;/strong&gt;: deletes, bulk updates, privileged actions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then enforce policy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read tools are widely available&lt;/li&gt;
&lt;li&gt;Write tools require explicit scopes and tighter budgets&lt;/li&gt;
&lt;li&gt;Danger tools require:&lt;/li&gt;
&lt;li&gt;preview -&amp;gt; apply&lt;/li&gt;
&lt;li&gt;confirmation tokens&lt;/li&gt;
&lt;li&gt;additional policy checks&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="preview---apply-pattern"&gt;Preview -&amp;gt; Apply pattern&lt;/h3&gt;
&lt;p&gt;For dangerous operations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;plan_*&lt;/code&gt; returns a plan summary + &lt;code&gt;plan_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;apply_*&lt;/code&gt; requires &lt;code&gt;plan_id&lt;/code&gt; + user confirmation&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This prevents &amp;ldquo;drive-by deletes&amp;rdquo; and supports audit.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="output-handling-never-execute-raw-model-output"&gt;Output handling: never execute raw model output&lt;/h2&gt;
&lt;p&gt;This is the most common real-world failure.&lt;/p&gt;
&lt;h3 id="rule-model-output-is-data-not-code"&gt;Rule: model output is data, not code&lt;/h3&gt;
&lt;p&gt;If the agent is generating:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;kubernetes YAML&lt;/li&gt;
&lt;li&gt;SQL statements&lt;/li&gt;
&lt;li&gt;curl commands&lt;/li&gt;
&lt;li&gt;Terraform changes
&amp;hellip;treat the output as untrusted data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OWASP&amp;rsquo;s LLM02 guidance exists because people keep wiring LLM output directly into execution paths. [4]&lt;/p&gt;
&lt;h3 id="safer-alternative-structured-intent---validated-execution"&gt;Safer alternative: structured intent -&amp;gt; validated execution&lt;/h3&gt;
&lt;p&gt;Instead of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LLM writes YAML -&amp;gt; apply&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LLM proposes a structured change request (schema)&lt;/li&gt;
&lt;li&gt;server validates:&lt;/li&gt;
&lt;li&gt;allowlisted fields&lt;/li&gt;
&lt;li&gt;bounded ranges&lt;/li&gt;
&lt;li&gt;namespace/tenant scope&lt;/li&gt;
&lt;li&gt;server executes with known-safe libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where &amp;ldquo;tool contracts&amp;rdquo; win.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="secrets-minimize-scope-rotate"&gt;Secrets: minimize, scope, rotate&lt;/h2&gt;
&lt;p&gt;Secrets are the other common failure path.&lt;/p&gt;
&lt;h3 id="minimum-viable-rules"&gt;Minimum viable rules&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Never&lt;/strong&gt; put long-lived secrets in prompts.&lt;/li&gt;
&lt;li&gt;Prefer short-lived tokens and scoped credentials.&lt;/li&gt;
&lt;li&gt;Inject secrets server-side, not in the model context.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OWASP&amp;rsquo;s Secrets Management Cheat Sheet is a good baseline for central storage, rotation, auditing, and least privilege. [5]&lt;/p&gt;
&lt;h3 id="scope-secrets-to-tenants-and-tools"&gt;Scope secrets to tenants and tools&lt;/h3&gt;
&lt;p&gt;Instead of &amp;ldquo;one OAuth token for everything,&amp;rdquo; mint:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;per tenant&lt;/li&gt;
&lt;li&gt;per tool category&lt;/li&gt;
&lt;li&gt;short TTL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When something goes wrong, you want the blast radius small and revocation easy.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="network-and-egress-controls"&gt;Network and egress controls&lt;/h2&gt;
&lt;p&gt;If your agent system can reach the open internet or internal networks, you need guardrails.&lt;/p&gt;
&lt;h3 id="egress-allowlists"&gt;Egress allowlists&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;allowlist domains for integrations&lt;/li&gt;
&lt;li&gt;block metadata IP ranges&lt;/li&gt;
&lt;li&gt;re-validate after redirects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OWASP&amp;rsquo;s SSRF prevention guidance provides practical patterns for validation and blocking internal addresses. [3]&lt;/p&gt;
&lt;h3 id="separate-network-planes"&gt;Separate network planes&lt;/h3&gt;
&lt;p&gt;Keep tool servers in a network segment that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;can reach only what they need&lt;/li&gt;
&lt;li&gt;cannot reach internal admin endpoints&lt;/li&gt;
&lt;li&gt;cannot reach secrets stores directly unless necessary&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="logging-and-audit-without-data-leaks"&gt;Logging and audit without data leaks&lt;/h2&gt;
&lt;p&gt;Logging is security. Logging is also a leak vector.&lt;/p&gt;
&lt;p&gt;OWASP&amp;rsquo;s Logging Cheat Sheet calls out that logs may contain personal and sensitive information and must be protected from misuse. [6]&lt;/p&gt;
&lt;h3 id="practical-logging-rules"&gt;Practical logging rules&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;do not log raw prompts by default&lt;/li&gt;
&lt;li&gt;do not log raw tool payloads by default&lt;/li&gt;
&lt;li&gt;log structured summaries:&lt;/li&gt;
&lt;li&gt;tool name&lt;/li&gt;
&lt;li&gt;action class&lt;/li&gt;
&lt;li&gt;resource IDs (safe identifiers)&lt;/li&gt;
&lt;li&gt;status&lt;/li&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;store audit events separately from debug logs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="audit-events-always-on"&gt;Audit events (always on)&lt;/h3&gt;
&lt;p&gt;Every write/danger tool should emit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;who / what / when / result&lt;/li&gt;
&lt;li&gt;plan_id / idempotency_key&lt;/li&gt;
&lt;li&gt;before/after resource identifiers (not content)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Audit is what makes &amp;ldquo;agents in production&amp;rdquo; defensible to security and compliance teams.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="a-production-checklist"&gt;A production checklist&lt;/h2&gt;
&lt;h3 id="identity-and-authorization"&gt;Identity and authorization&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Strong auth for clients.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Least-privilege scopes per tool.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; MCP HTTP authorization flow implemented where applicable. [2]&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="tool-contracts"&gt;Tool contracts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Tools tiered: read/write/danger.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Preview -&amp;gt; apply for dangerous actions.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Schema validation + bounded arguments.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="output-handling"&gt;Output handling&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; No raw model output is executed without validation (OWASP LLM02). [4]&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="secrets"&gt;Secrets&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Secrets never placed in prompts.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Short-lived, scoped tokens used.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Rotation/audit practices exist (OWASP Secrets Mgmt). [5]&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="network"&gt;Network&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Egress allowlists exist.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; SSRF protections implemented. [3]&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="logging-and-audit"&gt;Logging and audit&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Logs are redacted and access-controlled.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Audit events exist for all side-effecting tools.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Log systems protected per OWASP guidance. [6]&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;p&gt;[1] OWASP - Top 10 for Large Language Model Applications (v1.1): &lt;a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/" target="_blank" rel="noopener noreferrer"&gt;https://owasp.org/www-project-top-10-for-large-language-model-applications/&lt;/a&gt;
[2] Model Context Protocol (MCP) - Authorization (Protocol Revision 2025-11-25): &lt;a href="https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization" target="_blank" rel="noopener noreferrer"&gt;https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization&lt;/a&gt;
[3] OWASP - SSRF Prevention Cheat Sheet: &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html" target="_blank" rel="noopener noreferrer"&gt;https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html&lt;/a&gt;
[4] OWASP GenAI Security Project - LLM02: Insecure Output Handling: &lt;a href="https://genai.owasp.org/llmrisk2023-24/llm02-insecure-output-handling/" target="_blank" rel="noopener noreferrer"&gt;https://genai.owasp.org/llmrisk2023-24/llm02-insecure-output-handling/&lt;/a&gt;
[5] OWASP - Secrets Management Cheat Sheet: &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html" target="_blank" rel="noopener noreferrer"&gt;https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html&lt;/a&gt;
[6] OWASP - Logging Cheat Sheet: &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html" target="_blank" rel="noopener noreferrer"&gt;https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html&lt;/a&gt;
&lt;/p&gt;</content:encoded></item></channel></rss>