DocumentationAgent Action Firewall

Policy Templates

Ready-to-use policy templates for common security scenarios.

Starter Template

A minimal policy that denies all actions by default:

Go
package firewall

# Deny by default
default decision = {"result": "deny", "reason": "No matching policy"}

# Add your allow rules below
decision = {"result": "allow"} {
    # Example: Allow all GET requests
    input.action.operation == "GET"
}

Domain Allowlist

Only allow requests to approved domains:

Go
package firewall

default decision = {"result": "deny", "reason": "Domain not in allowlist"}

allowed_domains := [
    "api.company.com",
    "api.stripe.com",
    "api.github.com"
]

decision = {"result": "allow"} {
    input.action.tool == "http_proxy"
    url := input.action.params.url
    domain_allowed(url)
}

domain_allowed(url) {
    some domain in allowed_domains
    regex.match(sprintf("https?://%s", [domain]), url)
}

Read-Only Mode

Allow only read operations, require approval for writes:

Go
package firewall

default decision = {"result": "deny", "reason": "Operation not permitted"}

# Allow all read operations
decision = {"result": "allow"} {
    input.action.operation in ["GET", "HEAD", "OPTIONS"]
}

# Require approval for write operations
decision = {"result": "require_approval", "reason": "Write operations need approval"} {
    input.action.operation in ["POST", "PUT", "PATCH", "DELETE"]
}

Business Hours Only

Restrict actions outside business hours:

Go
package firewall

default decision = {"result": "require_approval", "reason": "Outside business hours"}

decision = {"result": "allow"} {
    business_hours
}

business_hours {
    hour := time.hour(time.now_ns())
    weekday := time.weekday(time.now_ns())

    # Monday-Friday, 9 AM - 5 PM
    weekday >= 1
    weekday <= 5
    hour >= 9
    hour < 17
}

PII Protection

Block actions that may expose personally identifiable information:

Go
package firewall

default decision = {"result": "allow"}

pii_patterns := [
    "ssn",
    "social_security",
    "credit_card",
    "password",
    "secret"
]

decision = {"result": "deny", "reason": "Potential PII exposure detected"} {
    input.action.tool == "http_proxy"
    body := json.marshal(input.action.params.body)
    lower_body := lower(body)
    some pattern in pii_patterns
    contains(lower_body, pattern)
}

Rate Limiting

Require approval when rate limits are exceeded:

Go
package firewall

default decision = {"result": "allow"}

# Require approval if too many requests in the last hour
decision = {"result": "require_approval", "reason": reason} {
    input.context.request_count_1h > 100
    reason := sprintf("Rate limit exceeded: %d requests in last hour", [input.context.request_count_1h])
}

# Hard deny if way over limit
decision = {"result": "deny", "reason": "Rate limit critically exceeded"} {
    input.context.request_count_1h > 500
}

Environment-Based

Different rules for production vs. development:

Go
package firewall

default decision = {"result": "deny", "reason": "Environment not configured"}

# Development: allow most actions
decision = {"result": "allow"} {
    input.context.environment == "development"
    input.action.operation in ["GET", "POST", "PUT", "DELETE"]
}

# Staging: require approval for writes
decision = {"result": "allow"} {
    input.context.environment == "staging"
    input.action.operation in ["GET", "HEAD"]
}

decision = {"result": "require_approval", "reason": "Staging write requires approval"} {
    input.context.environment == "staging"
    input.action.operation in ["POST", "PUT", "DELETE"]
}

# Production: strict controls
decision = {"result": "require_approval", "reason": "Production action requires approval"} {
    input.context.environment == "production"
}

Combined Template

A comprehensive policy combining multiple patterns:

Go
package firewall

default decision = {"result": "deny", "reason": "No matching policy"}

# 1. Block dangerous patterns first
decision = {"result": "deny", "reason": "Blocked domain"} {
    blocked_domain(input.action.params.url)
}

# 2. Allow safe read operations
decision = {"result": "allow"} {
    input.action.operation in ["GET", "HEAD"]
    safe_domain(input.action.params.url)
}

# 3. Require approval for writes
decision = {"result": "require_approval", "reason": "Write operation"} {
    input.action.operation in ["POST", "PUT", "PATCH", "DELETE"]
    safe_domain(input.action.params.url)
}

# Helper functions
blocked_domains := ["malicious.com", "untrusted.io"]
blocked_domain(url) {
    some domain in blocked_domains
    contains(url, domain)
}

safe_domains := ["api.company.com", "internal.company.com"]
safe_domain(url) {
    some domain in safe_domains
    contains(url, domain)
}

Next Steps