IronCurtain Documentation
repository·master·Indexed 20 days ago
https://github.com/provos/ironcurtainA secure runtime for autonomous AI agents that uses a human-readable constitution to derive deterministic security policies. It prevents ambient authority by intercepting agent actions (filesystem, git, network) through a policy engine and MCP servers. Features include a vuln-discovery workflow for vulnerability research, a Web UI for control, and support for Anthropic and OpenAI-compatible models via LiteLLM.
What's inside IronCurtain
- The Memory MCP Server is a persistent memory solution for LLM agents built on the Model Context Protocol (MCP). It provides semantic search, LLM-powered summarization, and automatic memory maintenance using a single SQLite file. Unlike many other memory servers, it requires zero external dependencies (no Docker, PostgreSQL, or Neo4j) because it handles vector search and keyword search in-process using SQLite extensions.
Overview of the LongMemEval Benchmark Harness
masterThe LongMemEval Benchmark Harness is a Python-based evaluation tool designed to test the
memory-mcp-serveragainst the LongMemEval benchmark (comprising 500 questions across 6 question types).The evaluation workflow follows these steps:
- Reset: For every question, the harness resets the memory database to ensure isolation.
- Ingest: It ingests haystack sessions into the memory server using
memory_storecalls. - Retrieve: It uses
memory_recall(ormemory_context) to fetch relevant context based on the question. - Generate: A reader LLM (e.g., Gemma3:27b via Ollama) generates a hypothesis answer based on the retrieved context.
- Evaluate: A judge LLM scores the hypothesis for correctness, producing accuracy metrics compatible with the official LongMemEval format.
This harness allows developers to verify how well the memory server handles temporal reasoning, knowledge updates, and multi-session retrieval.
Overview of the LoCoMo Benchmark Harness
masterThe LoCoMo (Long-Context Conversations for Memory-based Open-domain Dialogue) benchmark harness evaluates a memory MCP server's ability to handle long, multi-session conversations. It tests five specific reasoning skills:
- Single-hop retrieval: Finding information in a single session.
- Multi-hop synthesis: Combining information across multiple sessions.
- Temporal reasoning: Reasoning about dates and the order of events.
- Open-domain knowledge integration: Using external knowledge alongside conversation context.
- Adversarial detection: Identifying unanswerable questions.
The harness uses token-level F1 scoring (normalized) as its primary metric and evaluates retrieval accuracy using
dia_idtags.Messaging Transport Options for IronCurtain
masterIronCurtain supports various messaging platforms as transport layers for its vulnerability discovery workflow. When selecting a transport, consider the platform's API capabilities, rate limits, and interaction models (e.g., interactive messages, buttons, or text formatting).Comparison: Knostic OpenAnt vs IronCurtain vuln-discovery
masterThis research document compares the capabilities of Knostic OpenAnt against IronCurtain's
vuln-discoveryworkflow. It highlights specific technical advantages found in OpenAnt that IronCurtain currently lacks or handles differently, specifically regarding cost-efficiency, automated filtering, and structured reporting.Key areas of divergence include:
- Reachability Filtering: OpenAnt uses code-based call graph traversal to reduce LLM analysis costs, whereas IronCurtain relies on the LLM to manually trace call graphs via prompts.
- Static Analysis Seeding: OpenAnt uses CodeQL to exclude units already flagged by traditional SAST, while IronCurtain does not use static-analysis seeding.
- Prompt Customization: OpenAnt adjusts threat models based on application type (e.g.,
cli_toolvsweb_app), whereas IronCurtain relies on human-provided task descriptions. - Structured Output: OpenAnt enforces a strict schema for exploit paths in its verifier tools, while IronCurtain produces free-form markdown triage documents.
- Reporting & Deduplication: OpenAnt includes explicit modules for deduplication, evidence-tier rollup, and CWE tagging, and performs post-hoc deduplication of findings via call graphs.
Explore the IronCurtain project structure
masterThe project is organized into the following core directories:
src/index.ts: Entry point.src/cli.ts: CLI command dispatcher.src/config/: Configuration, constitution, and MCP server definitions.src/session/: Session management, budgets, and loop detection.src/sandbox/: V8 isolated execution environment.src/trusted-process/: Policy engine, MCP proxy, audit log, and escalation handler.src/pipeline/: Constitution to policy compilation pipeline.src/escalation/: Escalation listener, TUI dashboard, and state.src/mux/: Terminal multiplexer (PTY bridge, renderer).src/persona/: Persona management.src/memory/: Memory server integration.src/signal/: Signal messaging transport.src/daemon/: Unified daemon (Signal + cron scheduler).src/cron/: Cron job management.src/docker/: Docker agent mode and proxies.src/workflow/: Multi-agent workflow engine.src/web-ui/: Web UI backend.src/servers/: Built-in MCP servers.src/types/: Shared type definitions.packages/memory-mcp-server/: Standalone memory MCP server.
Overview of MITM Token Trajectory Capture
masterThe MITM Token Trajectory Capture system is designed to capture verbatim HTTP exchanges between Docker-mode agents (such as Claude Code or Goose) and upstream LLM providers (Anthropic, OpenAI, Google).
Key Characteristics:
- Output Format: Append-only JSONL, where each line represents one HTTP exchange.
- Fidelity: Captures byte-exact request bodies and reassembled response bodies (handling streaming SSE) suitable for SFT/RL training pipelines.
- Security: Designed to never leak real provider credentials; captured headers use the sentinel
fakeKeyinstead of the real swapped keys. - Reliability: Uses a 'poisoning' model—if a capture is incomplete due to memory pressure, write errors, or unsupported encodings (like
zstd), the entire session is flagged as poisoned rather than emitting partial, useless data. - Performance: The capture process is a 'tee' that runs in parallel to the forwarding path, ensuring it never blocks, slows, or interrupts the agent's connection.
Understand ToolCallCoordinator concurrency and safety
masterThe
ToolCallCoordinatoris a central component that managesPolicyEngine,AuditLog,CallCircuitBreaker,ApprovalWhitelist,AutoApprover, andServerContextMap. It is designed to handle $N$ concurrent agent tool-call streams (e.g., multipleresearcheroranalyzerlanes).Thread Safety Mechanism
The coordinator uses a FIFO call mutex (
AsyncMutex) to ensure that in-memory caches and audit logs are protected from race conditions. The following operations are serialized viathis.callMutex.withLock(...):handleToolCall(includesbuildCallToolDeps()andhandleCallTool())handleStructuredToolCallloadPolicy(acquires call-mutex then policy-mutex in a fixed order to prevent deadlocks)close()
Critical Risk: Mutex Stalling during Escalation
A known risk is that an agent-path policy escalation (where a human must approve a tool call) can hold the
callMutexfor the entire duration of the human response latency. This causes all other concurrent lanes to queue and freeze.Mitigation Strategy: The design requires that the
callMutexbe released during the escalation wait (awaitingautoApprove,onEscalation, orwaitForEscalationDecision) and re-acquired only to finish the call (writing the audit log, updating the circuit breaker, and handling transport).Handle context window exhaustion errors
masterIronCurtain does not perform automatic pruning or summarization of message history. If the message history exceeds the model's context window,
generateText()will throw an error.When this happens, the transport will surface an error message similar to:
Context window exceeded. Please start a new session.To avoid this, you should manage context manually or start a new session when approaching model limits.
Verify Logger interception and formatting
masterThe IronCurtain logger intercepts standard
consolemethods and redirects them to the configured log file. When testing or using the logger, note the following formatting rules:- Console Interception:
console.logandconsole.errorcalls are prefixed with[console.log]or[console.error]respectively in the log file. - Argument Formatting: Non-string arguments passed to
console.logare formatted as JSON strings. - Log Levels: The logger supports
debug,info,warn, anderror. Each entry in the log file includes an ISO timestamp and the level (e.g.,INFO,ERROR). - No-op Behavior: If
logger.setup()has not been called, calls tologger.info()orlogger.error()are no-ops and do not write anywhere.
// Example of how console calls are transformed in the log file: logger.setup({ logFilePath: logFile }); console.log('count:', 42, { key: 'value' }); // Log file content: [timestamp] [console.log] count: 42 {"key":"value"} console.error('some error'); // Log file content: [timestamp] [console.error] some error- Console Interception:
Configure OpenRouter via Provider Profiles
masterIronCurtain supports OpenRouter through named provider profiles. Instead of using a global setting, you define profiles in your configuration, allowing different sessions to use different providers (e.g.,
nativefor Anthropic/OpenAI andopenrouterfor OpenRouter-based models).To use a specific profile, you must specify it during session startup. If no profile is specified, IronCurtain falls back to the
modelProviders.defaultprofile defined in your configuration.# Start a session using a specific OpenRouter profile ironcurtain start --provider-profile my-openrouter-profileConfigure deterministic execution with containers
masterYou can configure deterministic states to run inside a Docker container by setting the
containerfield totruein your workflow configuration. This allows for isolated execution environments.Key configuration options for deterministic states include:
container: Boolean. Iftrue, the state executes within a Docker container.containerScope: String. Defines the scope for the container. If not provided, it defaults toDEFAULT_CONTAINER_SCOPE.timeoutMs: Number. The maximum execution time for the commands. If omitted, the system defaults to a 10-minute timeout via theDockerManager.
When running in a container, commands are executed in the
CONTAINER_WORKSPACE_DIRusing thecodespaceuser. The system uses a 'mint-on-demand' strategy: if a container for the specified scope does not exist, one is created (minted), re-attaching the persisted/workspacedirectory to ensure continuity from previous states.# Example YAML configuration for a deterministic state state_id: "my-test-state" run: - "npm test" - "npm run lint" container: true containerScope: "test-env-1" timeoutMs: 300000