← Back to Home

Security engineered in. Not bolted on.

Comis wasn't patched for security after launch. Every component was built from scratch with the question: what happens when an AI agent has real power and someone tries to abuse it?

On

Exec sandbox where supported

18

Skill content-scanner rules

0

Secrets in plaintext

Fail-closed

Broker & action classifier

Flagship feature

Sandboxed process isolation.

Shell commands are isolated with the strongest sandbox provider the host can supply. On supported Linux and macOS systems, the agent sees its workspace and approved runtime paths, not your whole machine.

Linux Bubblewrap (bwrap)
  • Full namespace unsharing - mount, PID, user, cgroup, IPC all isolated
  • Private /tmp and /dev - tmpfs mounts, no host filesystem leakage
  • Read-only system paths - /usr, /bin, /lib, /etc (subset) mounted read-only
  • --die-with-parent - sandbox process dies if daemon dies, no orphans
  • Network preserved - network isolation is a separate concern (SSRF guard)
macOS sandbox-exec (SBPL)
  • Default-deny profile - starts from (deny default), explicitly allows each capability
  • Dynamic SBPL generation - per-invocation profile based on agent workspace
  • Symlink resolution - resolves /tmp → /private/tmp for kernel path matching
  • Startup smoke test - verifies sandbox-exec works on current macOS version
  • Explicit downgrade - unavailable sandbox providers are detected and surfaced

Production runs on Linux. Docker Desktop's lightweight VM kernel can't run the exec sandbox - Comis detects unsupported dev/container sandbox hosts at startup, logs the downgrade, and auto-disables exec sandboxing rather than pretending isolation exists. Detection is explicit, not silent: you see it in the startup logs and choose how to proceed.

6 layers of exec defense, inside out:

Layer 1

Tool policy can remove exec entirely

Layer 2

Command denylist blocks rm -rf, mkfs, etc.

Layer 3

Env denylist blocks LD_PRELOAD, DYLD_*

Layer 4

CWD validation via safePath()

Layer 5

OS kernel sandbox (bwrap / sandbox-exec)

Layer 6

Subprocess env filtering strips API keys

Credential broker

Your API keys are never where the agent can read them.

Secrets live in an AES-256-GCM encrypted store; the key is injected at the network boundary, never inside the sandbox. The code that builds the sandbox env never even reads the real key. An in-process MITM broker terminates TLS with its own CA, validates a single-use session token, matches host and path against the allow-list, and swaps the placeholder at the header layer. It fails closed: any gate failure (407/403/502) destroys the tunnel before a single byte reaches upstream.

Credential broker deep dive →

Defense in depth

Layered runtime defenses, not a single guardrail.

Defense in depth - layered runtime defenses, benchmarked, not a single guardrail. Each layer protects against a specific attack vector; no single failure compromises the system.

5 Perimeter

Block threats before they reach the LLM

4 Secrets

Encrypt, scope, redact, and broker credentials at every layer

1 Network

Prevent outbound requests to private networks

1 Process Isolation

Sandboxed filesystem execution where the host supports it

3 Access Control

Limit what each agent can do and require approval

3 Memory

Partition trust levels to prevent memory poisoning

1 Detection

Detect when the LLM leaks system instructions

3 Transport

Authenticate and verify every connection

3 Runtime

Prevent runaway costs and sanitize tool output

3 Supply Chain

Screen skills and packages, block insecure code before merge

Every layer explained

What each layer protects against - and how.

The first principle: treat the LLM as the attack surface, not the security boundary. Every defense below works even if the model itself is fully compromised.

1

Input Guard

Perimeter

Protects against: Prompt injection & jailbreaks

A semantic scoring engine weighs jailbreak phrasing, role markers, dangerous commands, secret formats, prompt-extraction and credential-logging attempts. Typoglycemia detection catches scrambled-letter evasion; code-block exclusion avoids false positives. Three risk levels (low/medium/high) with configurable actions: pass, warn, reinforce, or block.

2

Output Guard

Perimeter

Protects against: Secret leakage & data exfiltration

Scans every LLM response for 15 secret patterns (AWS keys, bearer tokens, JWTs, database connection strings), canary token leakage, and system prompt extraction attempts. Critical findings are redacted as [REDACTED] before delivery.

3

External Content Wrapping

Perimeter

Protects against: Indirect prompt injection

All external content (web fetches, API responses, emails, webhooks) is wrapped in randomized 24-hex-char security delimiters with an explicit warning header. The LLM sees clear boundaries between trusted instructions and untrusted content.

4

Zero-Width Character Stripping

Perimeter

Protects against: Invisible character injection

Strips 15+ categories of invisible Unicode characters (U+200B-200F, U+2060, FEFF, U+00AD, tag block U+E0000-E007F) while preserving legitimate flag emoji. Prevents hidden instruction embedding.

5

Injection Rate Limiter

Perimeter

Protects against: Repeated injection attempts

Per-user sliding 5-minute window with progressive thresholds: warn at 3 detections, audit at 5. TTL-based eviction with 10K entry cap to prevent memory exhaustion.

6

Secret Manager

Secrets

Protects against: Credential exposure

AES-256-GCM encryption at rest with HKDF-SHA256 key derivation and per-encryption random salts. Defensive snapshot of environment at creation - no mutation tracking. No enumeration API. Diagnostic errors include the missing key name but never the value.

7

Scoped Secret Manager

Secrets

Protects against: Cross-agent credential access

Per-agent glob-pattern filtering (e.g., OPENAI_*, ANTHROPIC_*). Decorator pattern: indistinguishable from plain SecretManager. Audit events (secret:accessed) log every access attempt with success/denied/not_found outcomes.

8

Credential Broker

Secrets

Protects against: API key exposure via agentic CLIs

Works for API-key CLIs - Claude Code included. The real key stays in the daemon's AES-256-GCM encrypted store and is resolved per request by the in-daemon HTTPS broker. The CLI runs with a placeholder; the broker terminates TLS with its own CA, verifies the single-use proxy token, and injects the real credential for allow-listed hosts (`x-api-key`, `Authorization: Bearer`, or query param). On supported Linux hosts, broker-only network mode prevents direct egress from credentialed sandboxes. Broker failures stop before upstream forwarding: bad token -> 407, no binding -> 403, missing secret -> 502. Every inject, deny, and blocked-egress event is audited with `agentId` and `traceId`.

9

Log Sanitizer

Secrets

Protects against: Secrets in logs

Three layers deep: Pino fast-redact for structured fields, a regex-based sanitizer for free-text credential detection, and ReDoS mitigation with a 1MB input cap. Defense-in-depth - any single layer failing doesn't expose secrets.

10

SSRF Guard

Network

Protects against: Server-side request forgery

DNS-pinned URL validation before every outbound fetch. Blocks private RFC 1918 ranges, loopback, link-local, and explicitly blocks cloud metadata IPs (169.254.169.254 for AWS/GCP/Azure, 100.100.100.200 for Alibaba). HTTP/HTTPS only.

11

OS-Level Exec Sandbox

Process Isolation

Protects against: Filesystem escape & host compromise

Sandboxed filesystem isolation for shell commands where the host supports it. Linux uses bubblewrap (bwrap) with full namespace unsharing (mount, PID, user, cgroup, IPC). macOS uses sandbox-exec with SBPL deny-default profiles where available. Agents can be limited to their own workspace, with package manager caches redirected into that workspace and process tree kill cascades via --die-with-parent.

12

Tool Policy Engine

Access Control

Protects against: Unauthorized tool access

Named profiles (minimal, coding, messaging, supervisor, full) with group-based expansion. Per-agent allow/deny lists. The minimal profile exposes only exec, read, write - no memory, no web, no messaging.

13

Approval Gates

Access Control

Protects against: Unsupervised destructive actions

In-memory request queue with configurable timeouts. Dual caching: approval cache (30s) and denial cache (60s) with mutual invalidation. Batch parallel requests join existing pending entries. Graceful shutdown denies all pending.

14

Memory Trust Partitioning

Memory

Protects against: Memory poisoning via indirect injection

Three trust levels: system (platform-injected, highest), learned (from conversation), external (from tools/APIs/web, lowest). Low-trust sources can't overwrite high-trust memories. Provenance tracking records who stored each entry, from which channel, at which trust level.

15

Pre-Write Security Scan

Memory

Protects against: Dangerous patterns persisted in memory

Every memory entry passes through a security scan before storage. Blocks injection patterns, encoded payloads, and instruction-like content from being persisted where it could later surface via RAG retrieval and influence agent behavior.

16

RAG Trust Filtering

Memory

Protects against: Poisoned memories surfacing in retrieval

RAG retrieval excludes external-trust memories by default. Only system and learned memories are returned unless explicitly requested. Prevents low-trust content from web scrapes, API responses, or tool outputs from influencing agent reasoning through semantic search.

17

Canary Tokens

Detection

Protects against: System prompt extraction

Deterministic per-session HMAC-SHA256 tokens (CTKN_{16 hex chars}) injected into the system prompt. If the token appears in a response, the OutputGuard detects leakage and redacts it. Proves the LLM was tricked into revealing system instructions.

18

Bearer Token Authentication

Transport

Protects against: Unauthorized API access via token guessing

Timing-safe bearer token comparison using crypto.timingSafeEqual. Eliminates timing side channels that could leak token bytes through response latency differences. All API endpoints require authentication by default.

19

mTLS Authentication

Transport

Protects against: Unauthorized client connections

Mutual TLS certificate validation with Common Name (CN) extraction for client identity. Establishes cryptographic client identity at the transport layer before any application logic executes.

20

Webhook Verification

Transport

Protects against: Forged webhook deliveries

HMAC-SHA256/384/512 signature verification on all incoming webhooks. Timestamp freshness checks with a 5-minute replay window prevent captured webhook payloads from being replayed later.

21

Budget Guard

Runtime

Protects against: Runaway LLM costs

Three-tier token budgets (per-execution, per-hour, per-day) checked before the LLM call, not after. A prompt injection that tries to exhaust your API budget is stopped before it costs anything. Context window guard blocks at 95% utilization.

22

Circuit Breaker

Runtime

Protects against: Cascading provider failures

Three-state machine (closed/open/halfOpen) per model and provider. Tracks consecutive failures and latency. When open, returns a fallback response immediately instead of propagating the failure. Automatic recovery via half-open probes.

23

Tool Output Sanitizer

Runtime

Protects against: Indirect injection via tool results

Normalizes NFKC Unicode, strips invisible characters, detects instruction-like patterns in tool output, and truncates oversized results at newline boundaries (50K char default). Catches injection attempts that arrive through tool results rather than user input.

24

Skill Content Scanner

Supply Chain

Protects against: Malicious skills loaded at runtime

Every skill is screened before it can run. 18 rules cover exec injection, exfiltration, and XML breakout, applied at skill-load time. This is the canonical 18 - it belongs to the content scanner.

25

MCP Malware Screening

Supply Chain

Protects against: Known-bad third-party tool servers

MCP packages are checked against the OSV malware database before they ever spawn for the first time. A flagged package never starts.

26

ESLint Security Bans

Supply Chain

Protects against: Insecure code patterns reaching main

Named bans block insecure patterns in CI before merge: no path.join, no process.env, no eval/new Function, no swallowed errors - backed by architecture-as-tests that fail the build on regression.

27

Action Classifier

Access Control

Protects against: Unsupervised or unrecognized destructive actions

Destructive actions pause for HMAC-signed operator approval via chat buttons. Unknown action types classify as destructive and fail closed - the default is to stop and ask, never to assume an unrecognized action is safe.

Design principles

Why "security-first" isn't a marketing claim.

Single source of truth for all patterns

Every injection pattern, secret format, and dangerous command is defined once in injection-patterns.ts and shared across InputGuard, OutputGuard, Tool Sanitizer, and Memory Validator. No drift between components.

Constant-time comparisons everywhere

Bearer token verification, HMAC webhook validation, and secret comparison all use crypto.timingSafeEqual. No timing side channels.

Result type - no thrown exceptions

Every security operation returns Result<T, E>. Error handling is explicit and type-checked. No catch blocks hiding security failures.

Audit events on every decision

TypedEventBus emits security:warn, secret:accessed, approval:requested/resolved, and tool:executed events. Full audit trail without touching application logic.

Trust boundaries on memory

Memory entries carry provenance (who stored it, from which channel, trust level). External content from web/APIs cannot overwrite system or learned memories. RAG excludes external by default.

Pre-commit budget checks

Token budgets are checked before the LLM call, not after. A prompt injection that tries to exhaust your API budget is stopped before it costs you anything.

Audit every line. Run it on your infrastructure.

Comis is Apache-2.0-licensed, fully open source, and self-hosted. No telemetry, no cloud lock-in, no trust required.