The Ultimate 'Distrust': Zero Trust Permissions Model for Agents
What
For an Agent system, Zero Trust is not a networking buzzword; it is the "Permission Model for the Tool Execution Chain." It means defaulting to absolute distrust of any tool call, treating every side effect as an independent authorization decision, and strictly enforcing that decision at the execution point (PEP).
This article maps Zero Trust to implementable structures within an Agent runtime:
- PDP/PEP: Where exactly the Policy Decision Point and Policy Enforcement Point reside.
- ABAC (Attribute-Based Access Control): Authorization evaluates not just identity, but also task context and resource targets.
- Failure and Degradation: What happens when policy queries timeout or approval chains fail? (Timeouts, Degradation).
- Audit Evidence Chains: Every Permit/Deny decision must be fundamentally traceable (Auditing, Observability).
NIST SP 800-207 defines the logical components of a Zero Trust Architecture (PDP, PEP, etc.) and core principles, serving as the standard anchor for this engineering approach.
References:
- https://csrc.nist.gov/pubs/sp/800/207/final
- https://nvlpubs.nist.gov/nistpubs/specialpublications/NIST.SP.800-207.pdf
Problem
As an Agent gains access to an increasing number of tools, the traditional "issue a single API key" approach introduces massive structural risk:
- Over-Privilege: A single key grants access to all tools. A single prompt injection can trigger a massive privilege escalation (Permissions).
- Context-Blind Permissions: An Agent tasked with fixing CSS can suddenly delete a database, because authorization only checks identity, not intent.
- Retry Magnification: Timeouts triggering retries result in duplicate executions of irreversible actions (Idempotency, Retries).
- Untraceability: Post-incident, it is impossible to answer "Who permitted this call, why was it permitted, and what resources were affected?" (Auditing, Observability).
The goal of Zero Trust is not to "make the system harder to use," but to funnel the side-effect channel into a strictly governed protocol.
Principle
PDP and PEP: Policies Must Take Effect at the Point of Execution
The most critical boundary in Zero Trust is the separation of "Decision" and "Execution":
- PDP (Policy Decision Point): Computes a Permit/Deny verdict based on input attributes.
- PEP (Policy Enforcement Point): Forcibly enacts the PDP's result immediately before the actual tool execution, possessing the absolute authority to block, rate-limit, or terminate the session.
For Agents, the position of the PEP is highly specific: It sits exactly one layer in front of the tool registry / tool executor. Model outputs must never directly trigger side effects.
ABAC: Authorization Must Bind Task to Resource
The core premise of Attribute-Based Access Control (ABAC) is: Authorization is determined collectively by multiple attributes, not simply by "who you are." For an Agent, the most critical attributes typically include:
task_id/task_type: What is the current task?tool_name/tool_risk_level: What tool is being invoked, and what is its inherent risk tier?resource_targets: The target resource set (paths, domains, table names, project IDs).actor: Agent ID / User ID / Environment.history: Has a rejection been triggered recently? Is a retry storm occurring?
Usage
1) Tier Your Tools First (Risk Tiers)
Minimum recommended tiering:
read_only: Read-only queries, generates zero side effects.write_low: Writable but rollback-capable (e.g., generating a patch file, but not directly committing).write_high: Irreversible or high-risk (Deletions, Payments, Deployments, Permission modifications).
High-risk tools must default to HITL (Human-in-the-Loop) approval, mandating the display of visual diffs/previews (Auditing).
2) Policy-as-Code: Express Policies via OPA-like Decision Engines
Policies should not be scattered arbitrarily across your codebase as if/else statements. OPA (Open Policy Agent) provides an entry point for a policy-as-code decision engine, acting as your PDP: Input attributes, output a decision.
Reference: https://www.openpolicyagent.org/docs
3) An Implementable Policy File (Example)
This policy example emphasizes three things:
- Authorization tiered by tool.
- Allowlisting/Denylisting based on
resource_targets. - Explicitly defined timeout, retry, idempotency, and audit requirements.
# zero_trust_policy.yaml
rules:
- tool: "file_read"
risk: "read_only"
allow_paths: ["content/**", "src/**"]
deny_paths: [".env", "**/secrets/**", "~/.ssh/**"]
- tool: "apply_patch"
risk: "write_low"
allow_paths: ["content/**", "src/**"]
require_wal: true
require_idempotency_key: true
timeout_ms: 10000
max_retries: 1
- tool: "shell_exec"
risk: "write_high"
require_approval: true
allowed_commands: ["npm test", "npm run build", "git status"]
forbidden_commands: ["rm", "chmod", "curl", "sh"]
timeout_ms: 600000
max_retries: 0
4) PEP Implementation Skeleton: Forced Blocking Prior to Execution
class PolicyDecision:
def __init__(self, *, allowed: bool, reason: str):
self.allowed = allowed
self.reason = reason
class PolicyEngine:
"""PDP: Inputs attributes, outputs Permit/Deny."""
async def decide(self, *, tool_name: str, attrs: dict) -> PolicyDecision:
raise NotImplementedError
class ToolEnforcer:
"""
PEP: The forced enforcement point prior to tool execution.
"""
def __init__(self, *, policy: PolicyEngine, auditor):
self._policy = policy
self._auditor = auditor
async def call(self, *, tool_name: str, args: dict, attrs: dict):
decision = await self._policy.decide(tool_name=tool_name, attrs=attrs)
# CRITICAL: Audit logging must happen regardless of Permit or Deny
await self._auditor.record_policy_decision(tool_name, args, attrs, decision)
if not decision.allowed:
raise PermissionError(decision.reason)
return await self._execute(tool_name, args)
[!IMPORTANT]
record_policy_decisionis a foundational component of the audit evidence chain. It must be written to an immutable audit log (Auditing).
5) Timeouts, Retries, Idempotency: Zero Trust Must Encompass Reliability
Many engineers reduce Zero Trust to "Permit/Deny," but for Agents, this is vastly insufficient. You must integrate reliability directly into your policies:
- Timeouts: What happens if the policy query itself times out? What if tool execution times out? (Timeouts).
- Retries: Is a denied call retry-able? Is a permitted call retry-able upon failure? (Retries).
- Idempotency: If permitted, are the resulting side effects allowed to be replayed? This mandates Idempotency Keys + WAL (Idempotency, Auditing).
- Degradation: If the policy system goes down, does it default to Deny? Does it allow degrading to read-only? (Degradation).
HITL and Kill Switches (Humans are the Final Enforcement Gate)
For high-risk tools, the system must support:
- Visual Previews: Command previews, diff previews, resource target previews (Auditing).
- One-Click Kill Switch: Terminate the current task and violently terminate child processes to prevent cascading actions (Resource Release).
Pitfall
- Implementing Authentication but Skipping Authorization: Being logged in does not equal permission to operate (Permissions).
- Policies Scattered in Code: Impossible to review or rollback system-wide rules (Auditing, Rollbacks).
- PEP Misplaced: Attempting to enforce rules purely via the LLM prompt is meaningless (Isolation).
- No Timeouts on Policy Queries: A slow policy engine will fatally drag down the entire execution chain (Timeouts, Degradation).
- Missing Audit Evidence: Inability to answer "Why was this permitted/denied?" reduces the system to an un-debuggable black box (Auditing, Observability).
Debug
When debugging a Zero Trust system, follow this specific sequence:
- Policy Input: Are the
attrsfully populated (task_id,resource_targets, etc.)? - Policy Decision: Is the reason for rejection explicable? Was it captured in the audit log?
- PEP Enforcement: Did the PEP physically block the tool execution?
- Timeouts/Degradation: If the policy system was unavailable, did the default behavior align with expectations?
Minimal Schema for Audit Logs (Strongly Recommended to Hardcode)
A primary value of Zero Trust is "Accountability." Therefore, every decision must generate an audit record containing at least:
task_id/trace_idtool_nameresource_targetsdecision(permit / deny)reason_code(e.g., policy_rule_id)idempotency_key(for write operations)approved_by(if HITL was triggered)latency_ms(PDP decision duration, crucial for isolating timeouts)
Without these fields, you cannot answer "Why was this allowed/denied," and Zero Trust devolves into an opaque, frustrating interceptor (Auditing, Observability).
Handling Policy Query Timeouts (Mandatory Degradation Strategies)
The PDP itself is an external dependency. It will experience lag, timeouts, and outages. You must decide in advance:
- Default Deny (Recommended): If the PDP is unreachable, immediately deny all high-risk tools (Permissions).
- Read-Only Degradation: Permit
read_onlytools to execute, but aggressively denywrite_hightools (Degradation). - Circuit Breaking: If the PDP times out N consecutive times, suspend all side-effect tools and demand human intervention (Timeouts, Degradation).
If this isn't explicitly defined, your system will randomly permit or randomly deny during an outage, leading to an uncontrollable blast radius.
Policy Caching (Use with Extreme Caution)
The immediate engineering reflex is to cache policy decisions to boost speed. For Agents, caching introduces severe risk: If the context attributes shift, the cached decision may no longer be valid.
If policy caching must be implemented, it must satisfy:
- The cache key must include
task_id/tool_name/resource_targets/risk_level. - The TTL must be brutally short. Furthermore, only cache
permitdecisions, neverdenydecisions (to avoid permanent lockdown states). - Upon any sensitive event (e.g., a permission denial or anomalous tool invocation), immediately evict related caches (Auditing).
Incident Post-Mortem Template (Converting Permission Incidents into Iterative Inputs)
When privilege escalation or erroneous approvals occur, the post-mortem must answer:
- What were the attribute inputs (
attrs) for this call? - Why did the PDP issue a
permit? Which specific rule was triggered? - Did the PEP actually enforce the constraints bound to the permit (Timeouts / Idempotency / Path Allowlists)?
- Did a retry loop amplify the side effects? (Retries, Idempotency).
- How must the
policy-as-codebe modified to permanently prevent this specific class of incident? (Rollback, Auditing).
Source
- NIST SP 800-207: https://csrc.nist.gov/pubs/sp/800/207/final
- NIST SP 800-207 PDF: https://nvlpubs.nist.gov/nistpubs/specialpublications/NIST.SP.800-207.pdf
- OPA Docs: https://www.openpolicyagent.org/docs
- BeyondCorp: https://beyondcorp.com/