Version 1.0 | 2026-03-17
AceClaw defends across five dimensions: network isolation, permission enforcement, memory integrity, content boundaries, and data protection.
The daemon communicates exclusively via Unix Domain Socket (~/.aceclaw/aceclaw.sock). No HTTP, REST, or WebSocket listeners exist.
| Component | Security Property |
|---|---|
UdsListener |
Binds UDS with POSIX 700 permissions (owner-only connect) |
DaemonLock |
OS-level file lock prevents concurrent daemon instances; PID file is POSIX 600 |
| Socket cleanup | Stale socket files removed on startup to prevent ghost connections |
| Connection isolation | Each accepted connection runs on a dedicated virtual thread |
Tool operations are classified by risk level via PermissionLevel:
| Level | Auto-approved? | Tools |
|---|---|---|
READ |
Yes | read_file, glob, grep |
WRITE |
Needs approval | write_file, edit_file |
EXECUTE |
Needs approval | bash |
DANGEROUS |
Always needs approval | Destructive operations (rm -rf, git push --force) |
public sealed interface PermissionDecision
permits Approved, Denied, NeedsUserApproval {}All decisions are explicit — no silent failures. The compiler enforces exhaustive handling.
| Mode | Behavior |
|---|---|
normal (default) |
Prompts for WRITE/EXECUTE/DANGEROUS |
accept-edits |
Auto-accepts WRITE, prompts EXECUTE/DANGEROUS |
plan |
Read-only — denies all WRITE/EXECUTE/DANGEROUS |
auto-accept |
Accepts everything (use with caution) |
PermissionManager tracks per-session blanket approvals via ConcurrentHashSet. Once a user approves a tool for the session, subsequent calls skip the prompt. Approvals are cleared on session close.
Sub-agents receive filtered tool registries — they cannot access tools beyond their granted permission level, preventing privilege escalation.
Every persisted memory entry is signed with HMAC-SHA256.
| Property | Implementation |
|---|---|
| Signing | MemorySigner.sign() computes HMAC-SHA256(id|category|content|tags|createdAt|source) |
| Verification | MessageDigest.isEqual() — constant-time comparison prevents timing attacks |
| Key storage | 32-byte random secret at ~/.aceclaw/memory/memory.key (POSIX 600) |
| Tamper handling | Corrupted entries silently skipped on load, warning logged |
| Mutable field exclusion | accessCount and lastAccessedAt are excluded from the signable payload so that read-tracking does not invalidate signatures |
CandidateStore also uses HMAC signing for learning candidates (candidates.jsonl). All transitions are logged to candidate-transitions.jsonl for auditability.
SystemPromptBudget prevents the system prompt from consuming excessive context:
| Cap | Default | Purpose |
|---|---|---|
| Per-tier | 20,000 chars | Prevents any single memory tier from dominating |
| Total | 150,000 chars | Caps the entire assembled system prompt |
For smaller context windows, forContextWindow() scales the budget proportionally (up to 25% of effective window).
When a tier exceeds its cap, TierTruncator applies 70/20/10 truncation:
- 70% head (preserves core instructions)
- 20% tail (preserves recent additions)
- 10% marker (
<!-- [TRUNCATED] Original: N chars -->)
Protected tiers (Soul priority=100, Managed Policy priority=90) are never truncated.
Tool outputs are capped at 30,000 characters with a 40/60 head/tail split. This prevents a single tool result from flooding the context window.
Memory tiers are loaded in strict priority order (100 → 50). Human-authored content (Tiers 1-5) always outranks agent-generated memory (Tiers 6-8), ensuring operator intent takes precedence over learned knowledge.
| Threat | Mitigation |
|---|---|
| Cross-project leakage | SHA-256 hashed workspace paths under ~/.aceclaw/workspaces/. Separate JSONL per project. |
| Unbounded growth | Journal: 500 lines/day. MEMORY.md: 50KB/file, 500KB/workspace. Consolidator: dedup + merge + prune. |
| Path traversal | PathResolver.resolve() normalizes paths. RuleEngine and MarkdownMemoryStore validate file names (no /, \, ..). |
| Read-before-write | WriteFileTool requires existing files to be read first, preventing blind overwrites. |
| Process isolation | BashExecTool: 120s default timeout (max 600s), output capped at 30K chars, stdin redirected to /dev/null, process tree destruction on timeout. |
| Memory injection | Memories are plain text (not executable), loaded as markdown sections in the system prompt. |
| Stale memory pollution | MemoryConsolidator prunes entries >90 days with zero access. Similarity merge (>80% Jaccard) prevents near-duplicates. |
| Key file exposure | POSIX 600 on signing keys and PID files. |
| Principle | How AceClaw implements it |
|---|---|
| Defense in depth | Permission system + UDS isolation + HMAC signing + content budgets |
| Fail-safe defaults | Only READ auto-approved; all writes need explicit approval |
| Least privilege | Sub-agents get filtered tool registries; socket/PID files owner-only |
| Sealed exhaustiveness | PermissionDecision, PermissionLevel, MemoryTier — compiler enforces complete handling |
| Transparency | Compaction reports reduction %; truncation marked with comments; permission checks logged |
| Constant-time verification | HMAC comparison via MessageDigest.isEqual() prevents timing side-channels |