Skip to main content

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:

  1. 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": { ... }
    }
    }
  2. Human reviews and edits file (or uses CLI helper):

    # Approve
    echo '{"status": "APPROVED"}' > ~/.shadow-exec/approvals/{id}.json

    # Deny
    echo '{"status": "DENIED"}' > ~/.shadow-exec/approvals/{id}.json
  3. 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 resource
  • IPI-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 risk
  • HIGH: Security risk, requires approval
  • MEDIUM: Non-critical but should be reviewed
  • LOW: 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

  1. Order rules from specific to general — First match wins
  2. Use resource_tags for environment isolation — Prevent prod accidents
  3. Start with WARN, graduate to BLOCK — Validate rules before enforcing
  4. Add catch-all LOG_ONLY rule — Monitor everything not explicitly covered
  5. Document each rule with clear name — Future you will thank present you
  6. Test policies in dev before deploying to prod — Avoid blocking legitimate operations

Next Steps