Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ Result: ActionDeniedError — SSH key never read

---

## Runtime Authorization for AI Agents

<video src="https://github.com/user-attachments/assets/0fdf1ebb-6044-4288-9613-cd46f98cc284" autoplay loop muted playsinline></video>

*Prompt injection, data exfiltration, credential theft — blocked in under 15ms.*

---

## The Problem

AI agents are powerful. They can read files, run commands, make HTTP requests.
Expand Down Expand Up @@ -104,11 +112,27 @@ await provider.authorize({
const content = await fs.readFile(path); // Only runs if authorized
```

### 3. See it in action
### 3. Run the demo

**Option A: Docker (Recommended)**

Run the full end-to-end demo safely in Docker. This is the safest way to see the attack scenarios — nothing touches your real filesystem.

```bash
git clone https://github.com/PredicateSystems/predicate-claw
cd predicate-claw
cd predicate-claw/examples/demo
./start-demo.sh
```

The demo shows 4 scenarios with a real sidecar:
- SSH key exfiltration → **BLOCKED**
- Shell command injection → **BLOCKED**
- Data exfiltration → **BLOCKED**
- Legitimate file read → **ALLOWED**

**Option B: Unit test (mocked sidecar)**

```bash
npm install
npm run test:demo
```
Expand Down
18 changes: 18 additions & 0 deletions examples/demo/Dockerfile.demo
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Demo application container
FROM node:22-slim

WORKDIR /app

# Install TypeScript and tsx for running demo
RUN npm install -g tsx

# Copy package files and install dependencies
COPY package*.json ./
RUN npm install

# Copy demo files
COPY examples/demo/demo.ts ./demo.ts
COPY examples/demo/policy.demo.json ./policy.demo.json

# Wait for sidecar to be ready, then run demo
CMD ["tsx", "demo.ts"]
25 changes: 25 additions & 0 deletions examples/demo/Dockerfile.sidecar
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Pre-built sidecar container for fast startup
FROM node:22-slim

# Install curl for downloading binary
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Detect architecture and download appropriate binary
ARG TARGETARCH
RUN ARCH=$(echo ${TARGETARCH:-$(uname -m)} | sed 's/amd64/x64/' | sed 's/x86_64/x64/' | sed 's/aarch64/arm64/') && \
echo "Detected architecture: $ARCH" && \
curl -fsSL -o /tmp/sidecar.tar.gz \
"https://github.com/PredicateSystems/predicate-authority-sidecar/releases/latest/download/predicate-authorityd-linux-${ARCH}.tar.gz" && \
tar -xzf /tmp/sidecar.tar.gz -C /usr/local/bin && \
chmod +x /usr/local/bin/predicate-authorityd && \
rm /tmp/sidecar.tar.gz

# Copy policy file
COPY examples/demo/policy.demo.json /app/policy.json

EXPOSE 8787

# Run sidecar
CMD ["predicate-authorityd", "--host", "0.0.0.0", "--port", "8787", "--mode", "local_only", "--policy-file", "/app/policy.json", "--log-level", "info", "run"]
136 changes: 136 additions & 0 deletions examples/demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Predicate Authority Demo: Hack vs Fix

**See how Predicate Authority blocks prompt injection attacks in real-time.**

This demo shows an AI agent attempting to:
1. Read SSH private keys (blocked)
2. Run `curl | bash` commands (blocked)
3. Exfiltrate data to webhook.site (blocked)
4. Read legitimate project files (allowed)

## Quick Start

```bash
git clone https://github.com/PredicateSystems/openclaw-predicate-provider
cd openclaw-predicate-provider/examples/demo
./start-demo.sh
```

That's it. Docker handles everything.

## What You'll See

```
┌───────────────────────────────────────────────────────────────┐
│ PREDICATE AUTHORITY DEMO: Hack vs Fix │
├───────────────────────────────────────────────────────────────┤
│ │
│ [1/3] UNGUARDED: SSH Key Exfiltration │
│ Action: fs.read │
│ Resource: ~/.ssh/id_rsa │
│ Source: untrusted_dm │
│ │
│ RESULT: SUCCESS (THIS IS BAD) │
│ Output: "-----BEGIN OPENSSH PRIVATE KEY-----..." │
│ │
│ [1/3] GUARDED: SSH Key Exfiltration │
│ Action: fs.read │
│ Resource: ~/.ssh/id_rsa │
│ Source: untrusted_dm │
│ │
│ DECISION: DENY (12ms) │
│ Reason: deny_sensitive_read_from_untrusted_context │
│ │
│ Attack blocked. Sensitive data protected. │
│ │
└───────────────────────────────────────────────────────────────┘
```

## How It Works

```
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Agent │───▶│ Predicate │───▶│ Sidecar │
│ │ │ Provider │ │ (policy) │
│ fs.read │ │ │ │ │
│ ~/.ssh/... │ │ action:fs.read │ DENY │
└─────────────┘ │ source:untrusted └─────────────┘
└──────────────┘
ActionDeniedError
```

1. Agent receives tool call request
2. Provider intercepts and builds authorization request
3. Sidecar evaluates policy rules
4. Decision returned in <25ms
5. DENY = throw error, ALLOW = execute

## Key Properties

| Property | Value |
|----------|-------|
| **Deterministic** | Policy-based rules, not probabilistic filtering |
| **Fast** | p50 < 25ms authorization latency |
| **Auditable** | Every decision logged with mandate ID |
| **Fail-closed** | Sidecar errors block execution |

## Customize the Policy

Edit `policy.demo.json` to add your own rules:

```json
{
"rules": [
{
"id": "deny_my_secrets",
"effect": "deny",
"action": "fs.*",
"resource": ["**/secrets/*", "**/.env"],
"reason": "deny_secrets_access"
}
]
}
```

Then re-run `./start-demo.sh`.

## Requirements

- Docker (with Docker Compose)

No other dependencies. Everything runs in containers.

## Install in Your Project

```bash
npm install predicate-claw @predicatesystems/authorityd
```

```typescript
import { GuardedProvider, ToolAdapter } from "predicate-claw";

const provider = new GuardedProvider({
principal: "agent:my-agent",
});

const adapter = new ToolAdapter(provider);

// This will throw ActionDeniedError if policy denies
await adapter.readFile({
args: { path: "~/.ssh/id_rsa" },
context: { source: "untrusted_dm" },
execute: async (args) => fs.readFile(args.path),
});
```

## Links

- [GitHub: openclaw-predicate-provider](https://github.com/PredicateSystems/openclaw-predicate-provider)
- [npm: predicate-claw](https://www.npmjs.com/package/predicate-claw)
- [npm: @predicatesystems/authorityd](https://www.npmjs.com/package/@predicatesystems/authorityd)

## License

MIT / Apache 2.0
Loading