In a standard local development deployment, the Predicate sidecar loads plain YAML or JSON policy files without verifying signatures. While this provides a zero-friction developer experience, it presents a risk in shared or production environments: if an attacker gains host access, they could modify the local policy file to bypass restrictions (e.g., modifying a rule to effect: ALLOW).
To neutralize local file tampering, Enterprise deployments should enforce cryptographic policy signing.
┌─────────────────────────────────────────────────────────────────────────────┐
│ CONTROL PLANE │
│ ┌─────────────────┐ ┌──────────────────┐ ┌────────────────────────┐ │
│ │ Policy Editor │───>│ Ed25519 Signing │───>│ Signed Policy Payload │ │
│ │ (Admin UI/API) │ │ (Private Key) │ │ { policy, signature } │ │
│ └─────────────────┘ └──────────────────┘ └────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ LOCAL HOST / AGENT │
│ ┌────────────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │
│ │ Signed Policy File │───>│ Ed25519 Verify │───>│ Policy Engine │ │
│ │ policy.signed.json │ │ (Public Key) │ │ (Rules Active) │ │
│ └────────────────────────┘ └──────────────────┘ └─────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Invalid/Missing? │ │
│ │ REFUSE TO START │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
A signed policy file wraps the raw policy rules with cryptographic metadata.
JSON format (policy.signed.json):
{
"policy": {
"rules": [
{
"name": "allow-workspace-read",
"effect": "allow",
"principals": ["agent:*"],
"actions": ["fs.read"],
"resources": ["/home/*/workspace/**"]
}
]
},
"signature": "base64-encoded-ed25519-signature",
"signed_at": "2024-01-15T10:30:00Z",
"signed_by": "control-plane-v1"
}YAML format (policy.signed.yaml):
policy:
rules:
- name: allow-workspace-read
effect: allow
principals:
- "agent:*"
actions:
- fs.read
resources:
- "/home/*/workspace/**"
signature: "base64-encoded-ed25519-signature"
signed_at: "2024-01-15T10:30:00Z"
signed_by: "control-plane-v1"To enforce signature verification on your production agents, boot the Predicate sidecar with the signature enforcement flags:
predicate-authorityd \
--require-signed-policy \
--policy-signing-key <hex-public-key-from-control-plane> \
--policy-file policy.signed.json \
run| Flag | Environment Variable | Description |
|---|---|---|
--require-signed-policy | PREDICATE_REQUIRE_SIGNED_POLICY | Reject unsigned policies |
--policy-signing-key | PREDICATE_POLICY_SIGNING_KEY | Ed25519 public key (hex) |
When signature verification is enabled:
--require-signed-policy: Sidecar refuses to startIf you are building custom CI/CD deployment pipelines, you can interact directly with the Control Plane signing endpoints to automate policy distribution:
# Submit a raw JSON policy to receive the signed policy structure
curl -X POST https://api.predicatesystems.ai/v1/policies/sign \
-H "Authorization: Bearer $PREDICATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rules": [
{
"name": "production-policy",
"effect": "allow",
"principals": ["agent:prod-*"],
"actions": ["fs.read", "http.fetch"],
"resources": ["/app/**", "https://api.example.com/*"]
}
]
}'Response:
{
"policy": { "rules": [...] },
"signature": "a1b2c3d4e5f6...",
"signed_at": "2024-01-15T10:30:00Z",
"signed_by": "control-plane-v1"
}# Get the hex-encoded public key required for sidecar startup configuration
curl https://api.predicatesystems.ai/v1/signing/public-key \
-H "Authorization: Bearer $PREDICATE_API_KEY"Response:
{
"public_key": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890",
"algorithm": "ed25519",
"key_id": "cp-signing-key-v1"
}Here's an example GitHub Actions workflow that fetches a signed policy from the Control Plane and deploys it:
name: Deploy Signed Policy
on:
push:
paths:
- 'policies/**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Sign policy via Control Plane
run: |
curl -X POST https://api.predicatesystems.ai/v1/policies/sign \
-H "Authorization: Bearer ${{ secrets.PREDICATE_API_KEY }}" \
-H "Content-Type: application/json" \
-d @policies/production.json \
-o policies/production.signed.json
- name: Get signing public key
run: |
PUBLIC_KEY=$(curl -s https://api.predicatesystems.ai/v1/signing/public-key \
-H "Authorization: Bearer ${{ secrets.PREDICATE_API_KEY }}" \
| jq -r '.public_key')
echo "POLICY_SIGNING_KEY=$PUBLIC_KEY" >> $GITHUB_ENV
- name: Deploy to production
run: |
# Deploy signed policy and public key to your infrastructure
scp policies/production.signed.json prod-server:/etc/predicate/policy.json
ssh prod-server "systemctl restart predicate-authorityd"