Policy Reference
Complete reference for Shadow Executor policy YAML syntax.
Policy File Structure
version: "1.0"
name: "Policy Name"
rules:
- id: RULE-ID
name: Rule Name
severity: CRITICAL | HIGH | MEDIUM | LOW
action: BLOCK | WARN | REQUIRE_APPROVAL | BLOCK_AND_ALERT | LOG_ONLY
match:
service: string | string[]
operation: string | string[]
resource: string (glob pattern, optional)
resource_tags: Record<string, string> (optional)
ipi_score: string (optional, e.g., ">= 0.7")
ipi_class: string[] (optional)
Policy Actions
BLOCK
Prevent action execution immediately. Agent receives error, operation never reaches infrastructure.
- id: SE-001
name: Block production database deletion
severity: CRITICAL
action: BLOCK
match:
service: rds
operation: DeleteDBInstance
resource_tags:
Environment: production
Result: Action blocked, audit log entry created, agent receives BlockedActionError.
WARN
Allow action but log a warning. Useful for operations you want to track but not prevent.
- id: SE-002
name: Warn on S3 bucket deletion
severity: MEDIUM
action: WARN
match:
service: s3
operation: DeleteBucket
Result: Warning printed to console, audit log entry created, action proceeds.
REQUIRE_APPROVAL
Pause execution and wait for human approval.
- id: SE-003
name: Require approval for IAM changes
severity: HIGH
action: REQUIRE_APPROVAL
match:
service: iam
operation: [AttachUserPolicy, AttachRolePolicy, PutUserPolicy]
Result: Approval request created in ~/.shadow-exec/approvals/{id}.json, agent waits for manual approval/denial.
Approval workflow:
-
Shadow Executor writes approval request to file:
{"id": "550e8400-e29b-41d4-a716-446655440000","status": "PENDING","requested_at": "2026-05-06T12:00:00.000Z","timeout_minutes": 30,"decision": {"action": "REQUIRE_APPROVAL","matched_rule_id": "SE-003","agent_action": { ... }}} -
Human reviews and edits file (or uses CLI helper):
# Approveecho '{"status": "APPROVED"}' > ~/.shadow-exec/approvals/{id}.json# Denyecho '{"status": "DENIED"}' > ~/.shadow-exec/approvals/{id}.json -
Agent polls file, proceeds or aborts based on status
Note: Milestone 1 uses file-based approvals. Slack/Teams integration coming in Milestone 3.
BLOCK_AND_ALERT
Block action and send alert to configured channel (Slack, Teams, email).
- id: SE-004
name: Block and alert on root user actions
severity: CRITICAL
action: BLOCK_AND_ALERT
match:
service: iam
operation: "*"
resource: "arn:aws:iam::*:root"
Result: Action blocked, alert sent (stub in Milestone 1), audit log entry created.
Note: Alert delivery implementation coming in Milestone 3.
LOG_ONLY
Log action but do not enforce. Useful for monitoring mode.
- id: SE-005
name: Log all Lambda invocations
severity: LOW
action: LOG_ONLY
match:
service: lambda
operation: InvokeFunction
Result: Audit log entry created, action proceeds without warnings.
Match Conditions
service
Service name (e.g., rds, s3, iam, lambda, dynamodb).
Supports:
- Single value:
service: rds - Array:
service: [rds, dynamodb]
operation
Operation name in PascalCase (e.g., DeleteDBInstance, PutObject).
Supports:
- Single value:
operation: DeleteDBInstance - Array:
operation: [DeleteDBInstance, ModifyDBInstance] - Wildcard:
operation: "Delete*"(matches DeleteDBInstance, DeleteBucket, etc.)
resource (optional)
Resource ARN or glob pattern.
# Exact ARN
resource: "arn:aws:s3:::my-bucket/data/*"
# Glob pattern
resource: "arn:aws:rds:*:*:db:prod-*"
Note: If not specified, rule matches all resources for the service/operation.
resource_tags (optional)
Match resources with specific tags. All specified tags must match.
resource_tags:
Environment: production
Tier: critical
Tag matching behavior:
- All tags in policy must be present on resource
- Tag values must match exactly (case-sensitive)
- Additional resource tags are ignored
ipi_score (optional)
Match based on IPI detection score (0.0 = clean, 1.0 = definite injection).
Supported operators: >, >=, <, <=, ==
# Block if IPI score >= 0.7
ipi_score: ">= 0.7"
# Warn if IPI score between 0.4 and 0.7
ipi_score: ">= 0.4"
ipi_class (optional)
Match specific IPI attack classes detected.
ipi_class: [IPI-007, IPI-015]
IPI classes (Milestone 1):
IPI-001: Destructive operation on untagged resourceIPI-007: Base64-encoded payload or zero-width characters
Full IPI taxonomy coming in Milestone 2.
Rule Evaluation Order
Rules are evaluated in order from top to bottom. First match wins.
rules:
# This rule runs first
- id: SE-001
action: BLOCK
match:
service: rds
operation: DeleteDBInstance
resource_tags:
Environment: production
# This rule only matches if SE-001 didn't match
- id: SE-002
action: WARN
match:
service: rds
operation: DeleteDBInstance
Important: Order matters! More specific rules should come before general rules.
Default Rule
If no rule matches, the default action is LOG_ONLY.
To change default behavior, add a catch-all rule at the end:
rules:
# ... specific rules ...
# Catch-all: block everything not explicitly allowed
- id: SE-999
name: Default deny all
severity: HIGH
action: BLOCK
match:
service: "*"
operation: "*"
Severity Levels
Severity is informational and does not affect enforcement:
CRITICAL: Production-impacting, data loss riskHIGH: Security risk, requires approvalMEDIUM: Non-critical but should be reviewedLOW: Informational, monitoring only
Examples
Block All Destructive Operations in Production
- id: SE-PROD-DELETE
name: Block all deletions in production
severity: CRITICAL
action: BLOCK
match:
operation: "Delete*"
resource_tags:
Environment: production
Require Approval for IAM Changes
- id: SE-IAM-APPROVAL
name: Require approval for IAM policy changes
severity: HIGH
action: REQUIRE_APPROVAL
match:
service: iam
operation:
- AttachUserPolicy
- AttachRolePolicy
- PutUserPolicy
- PutRolePolicy
- CreateRole
- DeleteRole
Block High IPI Score Operations
- id: SE-IPI-BLOCK
name: Block suspected IPI attacks
severity: CRITICAL
action: BLOCK
match:
operation: "Delete*"
ipi_score: ">= 0.7"
Warn on S3 Public Access
- id: SE-S3-PUBLIC
name: Warn on S3 public access
severity: MEDIUM
action: WARN
match:
service: s3
operation: PutBucketAcl
Log All DynamoDB Operations
- id: SE-DYNAMODB-LOG
name: Log all DynamoDB operations
severity: LOW
action: LOG_ONLY
match:
service: dynamodb
operation: "*"
Policy Validation
Shadow Executor validates policy files on load using Zod schema validation.
Common validation errors:
Missing required fields:
Error: Policy rule SE-001 missing required field 'action'
Invalid action type:
Error: Invalid action 'ALLOW'. Must be one of: BLOCK, WARN, REQUIRE_APPROVAL, BLOCK_AND_ALERT, LOG_ONLY
Invalid IPI score operator:
Error: Invalid ipi_score operator '!>'. Must be one of: >, >=, <, <=, ==
Testing Policies
Use npx shadow-exec run to test policies in dry-run mode:
export SHADOW_EXEC_POLICY=./shadow-exec.policy.yaml
npx shadow-exec run
Or test with the demo:
npx shadow-exec demo
Best Practices
- Order rules from specific to general — First match wins
- Use resource_tags for environment isolation — Prevent prod accidents
- Start with WARN, graduate to BLOCK — Validate rules before enforcing
- Add catch-all LOG_ONLY rule — Monitor everything not explicitly covered
- Document each rule with clear name — Future you will thank present you
- Test policies in dev before deploying to prod — Avoid blocking legitimate operations
Next Steps
- MCP Integration Guide — Use policies with MCP servers
- Claude Code Integration — Protect Claude Code with policies
- Audit Logging — Query and verify audit logs