CVE-2026-109437: Unauthenticated RCE via Local Shell Backend
An unauthenticated remote code execution vulnerability in Cognition versions before v0.13.0 lets anyone who can reach the server have its AI agent run arbitrary commands on the host. In its default configuration, the API has no authentication and the agent has an unsandboxed shell tool.

Overview
Cognition is a self-hosted AI agent server built on LangChain's Deep Agents framework.
In its default configuration, the server exposes its REST API with no authentication and runs the agent on a local shell backend, which gives the agent an ungated execute tool that runs shell commands directly on the host.
An unauthenticated attacker who can reach the server can create a session, send a message asking the agent to run a command, and have that command executed on the host as the server process, including access to credentials such as GH_TOKEN that the backend passes through
Because anyone who can reach a default Cognition server over the network can make its agent run commands on the host, with no credentials and no user interaction, exposed deployments should be taken off the network or put behind authentication immediately.
Affected Product
Affected Files
- server/app/main.py:245-274 (router mounting, no auth middleware)
- server/app/settings.py:137-140, 185-192, 195-198 (default backend, tool gates, scoping default)
- server/app/agent/sandbox_backend.py:34-63, 576-622 (CognitionLocalSandboxBackend, create_sandbox_backend)
- server/app/agent/cognition_agent.py:386-407, 501, 637-727 (_create_sandbox, backend binding)
- server/app/api/routes/sessions.py:193-268 (POST /sessions, no auth)
- server/app/api/routes/messages.py:785-847 (POST /sessions/{session_id}/messages, no auth)
- server/app/llm/deep_agent_service.py:347-466 (stream_response, ReAct loop)
- server/app/storage/config_models.py:161-164, 432 (interrupt_on defaults)
- server/app/api/scoping.py:97-113 (non-authenticating scope check)
Root Cause
No authentication middleware or route-level dependency exists on any endpoint in server/app/main.py:245-274. The default sandbox backend is "local" (settings.py:137-140), implemented as CognitionLocalSandboxBackend(LocalShellBackend, SandboxBackendProtocol) (sandbox_backend.py:34), which uses deepagents' LocalShellBackend and causes deepagents to auto-expose the execute shell tool with shell=True semantics.
interrupt_on defaults to all-False (config_models.py:432) and blocked_tools/excluded_tools default to [] (settings.py:185-192), so the shell tool is ungated.
An unauthenticated attacker creates a session via POST /sessions and posts a message via POST /sessions/{id}/messages; the Deep Agents ReAct loop calls CognitionLocalSandboxBackend.execute(), running arbitrary commands on the host.
PoC
Deterministic mode - no LLM or running server required:
git clone --depth 1 https://github.com/CognicellAI/Cognition.gituv venv --python 3.12 cogvenv && VIRTUAL_ENV=$(pwd)/cogvenv uv pip install "deepagents>=0.6.2" structlog./cogvenv/bin/python poc_backend_exec.py ./CognitionLoads target's verbatim server/app/agent/sandbox_backend.py, calls create_sandbox_backend(sandbox_backend="local") (the default), invokes backend.execute("id").
Confirmed output:
backend class: CognitionLocalSandboxBackendid -> uid=501(user) gid=20(staff) ... exit_code=0uname -a -> Darwin ... arm64 exit_code=0Shell metacharacters (pipes, &&, ;, arithmetic expansion) confirmed interpreted, consistent with shell=True in the local backend.
Live end-to-end (operator-started instance with LLM configured):
BASE=http://localhost:8000 AGENT=default ./poc_http_unauth.shSends unauthenticated POST /sessions then POST /sessions/{id}/messages with no auth headers. Looks for tool_result containing uid=... gid=....
Impact
An unauthenticated network attacker who can reach the Cognition HTTP port obtains remote code execution as the server process with no credentials and no user interaction required.
The local backend explicitly passes through GH_TOKEN, HOME, and PATH, exposing those credentials to any command the agent executes.
Session scoping provides no authentication boundary: it is disabled by default and, when enabled, uses self-asserted request headers with no signature or secret, satisfiable by any attacker who mints their own session. The README quickstart documents the unauthenticated curl flow, and the product's own security documentation (docs/concepts/security.md:104) acknowledges authentication is assumed to be provided by an external gateway that does not exist in the default deployment.
Suggested Remediation
1. Upgrade Cognition to v0.13.0 or later, where the local shell backend is disabled unless explicitly enabled.
2. Do not set COGNITION_ALLOW_UNSAFE_LOCAL_EXECUTION=true outside isolated development. The README's Docker Compose quick start sets it to true, so remove it from deployments based on that file.
3. Place the Cognition API behind an authenticating gateway or reverse proxy, and do not expose port 8000 dire.ctly. Cognition does not authenticate API callers itself.
4. Require human approval for the execute tool (interrupt_on), or block it, on agents that process untrusted input.
Additional Resources
- CVE-2026-109437 record