escapes
escapes
escapes is a Rust binary for local privilege escalation via the OpenApe grant system. It runs as a setuid binary that verifies an AuthZ-JWT before executing a command with elevated privileges.
Think of it as sudo with cryptographic authorization -- instead of a password, you need a signed grant token approved by a human.
Installation
# Build from source
cargo build --release
# Install with setuid (requires root)
sudo make install # installs to /usr/local/bin/escapes
Agent Enrollment
Each machine needs an enrolled agent with a key pair:
sudo escapes enroll \
--server https://id.example.com \
--agent-email deploy@example.com \
--agent-name web-deploy \
--key /etc/openape/agent.key
The enrollment registers the agent's public key at the IdP. The private key stays on the machine, owned by the agent's user.
Usage
# Execute a command with a grant token
escapes --grant <jwt> -- apt-get upgrade
# With reason (logged for audit)
escapes --grant <jwt> --reason "Security update" -- systemctl restart nginx
The typical flow with the apes CLI:
# apes handles the full lifecycle: request grant, wait for approval, execute
apes run --as root -- apt-get upgrade
When --as is specified, apes run automatically routes through escapes for privilege escalation.
Security Model
Privilege Handling
- Starts as root (setuid binary)
- Drops privileges before loading any user data or keys
- Validates the AuthZ-JWT -- checks signature, audience, expiry, command hash
- Re-elevates only after successful validation
- Sanitizes environment -- clears
LD_PRELOAD,PATH, etc. before exec
Command Hash Verification
The JWT contains a cmd_hash (SHA-256 of the canonicalized command). escapes recomputes the hash from the actual command arguments and compares:
Requested: apt-get upgrade
cmd_hash: sha256:a1b2c3... (from JWT)
Computed: sha256:a1b2c3... (from actual args)
Match → execute
This prevents substitution attacks -- even if an attacker obtains a valid JWT, they cannot use it for a different command.
Multi-Agent Support
A single machine can have multiple enrolled agents, each with their own key and identity. escapes matches the JWT's subject against the registered agents by deriving the public key from the configured private keys.
Audit Logging
Every execution is logged as JSONL:
{
"ts": "2025-01-15T10:30:00Z",
"agent": "deploy@example.com",
"command": ["apt-get", "upgrade"],
"grant_id": "3f8a...",
"decided_by": "alice@example.com",
"result": "success"
}
Integration with apes CLI
The apes run command integrates escapes seamlessly:
# Direct: agent runs the command itself (adapter mode)
apes run -- kubectl apply -f deployment.yaml
# Escalated: agent runs the command as root via escapes
apes run --as root -- apt-get upgrade
In escalated mode, apes requests a grant with audience: "escapes", waits for approval, then passes the AuthZ-JWT to the escapes binary.
Next Steps
- Capabilities & Grants -- how the grant system works
- Delegation -- act on behalf of another user
- Quick Start: Agent -- enroll your first agent