Security Model
AEX contracts act as an enforceable layer between intent and tool execution. The runtime and adapters uphold the following guarantees:
- Contracts are parsed and validated before execution.
- Tool calls must appear in
use, be absent fromdeny, and pass the runtime policy intersection. - When both a policy and task contract are active, effective permissions use the most restrictive combination: allow is intersected, deny is unioned, confirm is unioned, budget takes the minimum.
- Confirmation gates pause execution until an approval handler allows the call.
- Budgets stop execution when the permitted number of
do/makesteps is exhausted. - All tool calls, confirmations, checks, and return values are logged.
- The MCP proxy (
aex proxy) enforces the same rules on every tool call between your client and upstream servers.
Runtime Protections
Command Injection Prevention
Built-in tools like tests.run use execFile rather than shell-based exec. Commands are split into an executable and argument array, preventing injection via shell metacharacters like ;, &&, |, or backticks. The runtime rejects any command argument containing shell chaining operators.
Path Traversal Prevention
The built-in file.read and file.write tools enforce a working-directory boundary. Any path that resolves outside process.cwd() (e.g., ../../../etc/passwd or an absolute path like /etc/shadow) is rejected before the filesystem is touched.
Policy Path Qualifiers
Runtime policy entries support path-scoped rules like file.read:/workspace/**. The runtime parses both the tool name and the path pattern from policy entries, preserving the path qualifier for future enforcement instead of discarding it.
Wildcard Matching
Tool permission wildcards enforce a dot boundary: network.* matches network.fetch and network.post but does not match networkx.anything. A shared matching implementation is used consistently across the parser, validator, runtime, and MCP gateway.
Timing-Safe Signature Verification
The aex verify command uses crypto.timingSafeEqual to compare HMAC signatures, preventing timing side-channel attacks that could progressively leak the expected signature.
Threat Model
AEX is designed to mitigate:
- prompt-injection attempts that ask an agent to read secrets or call undeclared tools
- exfiltration via overbroad tool permissions (blocked by
denyrules enforced before any tool executes) - silent edits that skip tests or checks
- tool calls that should require human approval (e.g.,
file.write,ticket.create) - path traversal attacks through user-controlled file paths
- command injection through crafted test commands
- permission escalation when a task contract requests broader access than the ambient policy allows (merge semantics enforce the intersection)
- generated contracts that bypass policy (
aex draftvalidates against policy;aex reviewshows effective permissions before execution)
What AEX does not guarantee:
- the correctness of a model-generated artifact (
makesteps still depend on the underlying model) - protection against compromised tool implementations
- sandboxing of arbitrary shell commands (use specialized tools instead of
shell.exec)
Signed Contracts & Provenance
Use the CLI to generate and verify cryptographic metadata:
aex sign tasks/fix-test.aex --id release-bot --key-file ./keys/aex.hmac
aex verify tasks/fix-test.aex --signature tasks/fix-test.aex.signature.json --key-file ./keys/aex.hmacSignature files capture the source path, SHA-256 hash, signer, timestamp, and HMAC digest. Store the signatures in your repository alongside contracts so platform teams can audit every change before allowing execution.
Threat-Model Demo
The Threat Monitor example demonstrates how to wire policies, confirmations, git tooling, and diff-aware checks together before mutating a repository. Pair it with signed contracts to guarantee the workflow hasn't changed since approval.
Compatibility Tests
The reference implementation includes tests that ensure the CLI, runtime, and LangGraph compiler agree on step ordering and semantics. When you run npm test, vitest executes:
- Command injection prevention (shell metacharacters blocked).
- Path traversal prevention (out-of-cwd paths rejected).
- Runtime checks for unified diff validation and file-permission enforcement.
- Git tool integrations (
git.diff,git.apply) under a temporary repository. - Cross-runtime verification that
taskToLangGraphproduces the same step count as the validated task. - Timing-safe signature verification and tamper detection.
MCP Proxy Security
The aex proxy command enforces policy on MCP tool calls at the transport layer — between your client (Claude Code, Codex CLI) and upstream MCP servers. This provides defense-in-depth because:
- Deny rules are enforced before the upstream server sees the request. A prompt injection that convinces the model to call a denied tool is blocked at the proxy, not at the model.
- Budget enforcement stops execution after the configured number of calls, preventing runaway agents.
- Audit logging records every decision (allowed, denied, confirmed) as structured JSON to stderr.
aex proxy --policy .aex/policy.aex -- your-mcp-serverResources
- Policy Reference —
.aexpolicy file format and merge semantics - Policy schema
- JSON IR schema
- Runtime audit logs emitted by
aex run(--loggerintegrations can stream them elsewhere). - Threat Monitor contract