The Quick Start Is the Exploit: Cognition CVE-2026-109437

At 19:17:19Z on 19 October 2026, NVD published CVE-2026-109437, assigned by VulnCheck, rated 9.2 critical on CVSS 4.0 and 9.8 on CVSS 3.1, carrying two CWEs that are worth reading as a pair: CWE-1188, initialization of a resource with an insecure default, and CWE-306, missing authentication for a critical function.

The description, quoted from the record, is unusually complete for a VulnCheck advisory and names the request sequence: Cognition before 0.13.0 “contains an unauthenticated remote code execution vulnerability due to defaulting its agent sandbox backend to local execution and shipping no authentication on its REST/SSE API. Attackers can create a session via POST /sessions and post a message via POST /sessions/{id}/messages without credentials, causing the Deep Agents ReAct loop to run attacker-directed shell commands through the local shell backend, resulting in remote code execution as the server process.” Credit goes to Noy Pearl, Michael Sromin and Ophir Dror of Lasso Security.

Cognition (CognicellAI/Cognition, MIT, Python, created 16 February 2026) is small — 11 stars, 3 forks — and we are not going to pretend otherwise. It is worth a briefing anyway, for two reasons that generalise well past this repository. The first is that the exploit is the quick start, reproduced from the project’s own README, which still documents the unauthenticated sequence today. The second is that the record is a textbook case of two CWEs where only one got fixed, and the one left standing is the one the project considers somebody else’s job.

What the project is, and why the default matters

Cognition describes itself as “a headless backend that handles the hard infrastructure problems of production AI agents: sandboxed execution, durable session state, and full observability,” built on Deep Agents and LangGraph. Its README states the problem it solves first, and the first bullet is the relevant one, quoted verbatim: “Isolation: How do you let an agent run code or shell commands without endangering your infrastructure?”

That framing is what makes the defect interesting rather than merely bad. This is not a project that forgot agents execute code. It is a project whose entire stated purpose is to put a boundary around that execution, which shipped with the boundary set to none. The sandbox backend is a configurable abstraction; the default value selected the local shell, meaning the agent’s tool calls landed in the process’s own host rather than in anything isolated. CWE-1188 is the precise classification and it is doing real work here: nothing was missing from the design, and the shipped value of one setting undid it.

The second half is the delivery mechanism. The REST/SSE API has no authentication, so there is no step between a network path to the port and a message in the agent’s inbox. Combine them and the ReAct loop — which exists to decide which tool to call next based on the message it was handed — becomes a remote command interpreter for anyone who can reach it. The attacker does not need to find a tool-calling bug or escape a sandbox. They write the task in English, and the agent performs it correctly.

Here is the README’s Docker Compose quick start, which we read at tag v0.16.3 — the current release, three minor versions past the fix:

curl -s -X POST http://localhost:8000/sessions -H "Content-Type: application/json" -d '{"title": "My first session"}', then curl -N -X POST "http://localhost:8000/sessions/$SESSION/messages" -H "Content-Type: application/json" -d '{"content": "List the files in the workspace."}'.

Those are the two endpoints the CVE names, in order, with no credential on either, and the sample prompt is a filesystem operation. The documentation and the proof of concept are the same text. We note it as a fact about the current README rather than as evidence the current version is exploitable, because it is not — but a reader reaching for the quick start is being shown a shape that only stays safe because of a default they are not being told about.

The fix shipped eighty-three days before the advisory, as a feature

Cognition v0.13.0 was released on 28 July 2026 at 01:19:11Z. The CVE published on 19 October. That is 83 days during which the fixed version was on the shelf and nothing told an operator why they wanted it.

The v0.13.0 release notes are long and substantive — a multi-tenant rework with scope keys, agent revisions, definition digests, pinned run manifests and an OpenTelemetry rebuild. There is no security section, no CVE reference and no advisory. The fix appears as the eighth bullet in the Added list, and we quote it in full because the wording is precise about what it does: “Added strict production execution settings that fail closed for unsupported host/local execution, attached Python tools, unsafe callbacks, and sandbox fallback paths unless explicit development flags are enabled.” A sibling bullet adds the related control: “Added operator-controlled callback origin allow-listing; per-message callbacks are denied unless their HTTPS origin is explicitly approved.”

That is a good fix. “Fail closed unless explicit development flags are enabled” is exactly the right correction for CWE-1188, and it covers more ground than the reported issue — attached Python tools and sandbox fallback paths were not in the advisory. The project found the class, not just the instance.

What it is not is a security disclosure. Formatted identically to the forty other bullets around it, carrying no severity, no identifier and no statement that earlier versions are remotely exploitable, it reaches an operator as a feature they can schedule. This is the same pattern we measured in Gitea’s 28.2.0 release, where five CVEs including an authentication bypass sat under “Bug Fixes” in a line formatted like a spacing fix, and the same one we recorded for OneUptime and LobsterAI. The cost falls entirely on operators who upgrade deliberately rather than continuously: the one who took v0.13.0 for the multi-tenancy work was protected in July and never knew, and the one who read the breaking-changes list, decided the migration could wait, and pinned v0.12.0 ran a remotely exploitable build for three months on the basis of an accurate reading of the only document they were given.

The CWE that was not fixed

This is the part we want to be careful about, because it is the finding and it is also the easiest thing to overstate.

The CVE names two weaknesses. CWE-1188 is fixed in v0.13.0, by the fail-closed execution settings quoted above. CWE-306, missing authentication for a critical function, is not addressed by that change at all — and on the project’s own account it is not meant to be. The v0.13.0 highlights include a statement of scope we quote verbatim: “Preserved Cognition’s backend mission by keeping tenant IAM, billing, trace retention, redaction, MLflow experiment ownership, and publishing UX as builder/operator responsibilities.”

Identity and access management is explicitly out of scope, by design, as a documented product decision. The v0.16.3 README’s quick start is consistent with that: it still shows two uncredentialed POSTs, because there is nothing to authenticate with. So what v0.13.0 changed is what an unauthenticated message can make happen, not whether an unauthenticated message is accepted. On a current deployment, a stranger who can reach port 8000 can still create sessions and drive the agent; they are now driving it through whatever sandbox the operator configured, and the server refuses to start in an unsafe local-execution mode without an explicit development flag.

Is that a vulnerability? We think the honest answer is that it is a boundary disagreement of exactly the kind we examined in the bootc signature-policy pair last week, and both positions are coherent. A library that deliberately delegates IAM to its embedder is not obliged to ship an auth middleware, and Cognition says so in writing. A CVE describing a deployment — the Docker Compose path the README puts first, on a host someone exposed — is a statement about what operators actually run. The useful output is not a verdict but a warning for anyone building on this class of component: when an agent runtime documents that authentication is your job, the sandbox default is the only control standing between the network and the tool calls, and it is one configuration value. v0.13.0 made that value fail closed. Nothing made the API require a credential, and nothing will.

What to do

Run v0.13.0 or later; current is v0.16.3 (9 October 2026), and there is no reason to stop at the version named in the CVE when three minors of multi-tenant isolation work sit above it. If you are pinned below v0.13.0, treat the upgrade as urgent rather than scheduled regardless of what the release notes called it.

Then do the part the upgrade does not do. Put authentication in front of the API yourself — a reverse proxy enforcing tokens, or the tenant IAM the project explicitly leaves to you. Confirm the port is not reachable from anything but that proxy; a default Docker Compose bring-up listening on 0.0.0.0:8000 on a cloud host is the deployment the advisory describes. Verify the sandbox backend explicitly in configuration rather than trusting the default, and confirm no development flag re-enables host execution in a production manifest, since that flag is now the documented route back to the vulnerable behaviour. If you ran any version below v0.13.0 on a reachable network, treat the host as having accepted arbitrary commands from anyone who found it: rotate the provider API keys in that environment, since OPENAI_API_KEY in a .env file is step two of the quick start and is readable by the shell the agent was holding.

The generalisable check, which costs nothing and applies to every agent harness in this category: send one unauthenticated POST to your own deployment and see whether the agent answers. If it does, the sandbox configuration is your entire security model, and you should know that as a measured fact rather than an assumption. We have now written up an MCP workspace that auto-connected into RCE, an unauthenticated actor pool deserialising cloudpickle, and a Google agent mesh whose ingress failed open, and the shared root is not a parsing bug or a clever injection. It is that the component which decides whether this caller may speak to the agent was assumed to exist somewhere else.

CVE-2026-109437 is not in the CISA KEV catalogue (checked directly, version 2026.10.16, 1,748 entries, zero hits), and no exploitation has been reported. There is no GitHub Security Advisory for it: the repository’s advisory list is empty, so the identifier will not reach a dependency scanner by that route — and since the package is installed from a git URL rather than PyPI in the documented flow, it may not reach one at all.

Our verification was read-only. The CVE identifier, publication timestamp of 2026-10-19T19:17:19.807Z, vulnStatus, the disclosure@vulncheck.com source identifier, the full description, both CWE assignments, and the CVSS 4.0 and 3.1 vectors and scores were read first-hand from the NVD 2.0 API. The severity rating, affected range, researcher credits and advisory text were read directly from the VulnCheck advisory page. Repository metadata (11 stars, 3 forks, MIT, Python, created 2026-02-16, last pushed 2026-10-09, not archived, 40 tags), the complete release list, and the full v0.13.0 release body with its publication timestamp of 2026-07-28T01:19:11Z were read first-hand from the GitHub API; every quoted release-note line is verbatim from that body, and the absence of a security section in it was confirmed by reading the whole document. The quoted README text and the two quick-start curl commands were read from the repository at tag v0.16.3. The empty repository advisory list and the current release of v0.16.3 were measured directly. KEV status was checked directly against the published catalogue. Brave Search was used for discovery only and returned nothing but automated CVE mirrors — Threat Radar, threatint, strix.ai and one aggregator — with no independent technical analysis of the record. We installed nothing, started no Cognition server, created no session, sent no message to any endpoint, and executed no proof of concept; the request sequence quoted above is the vendor’s own documentation and the advisory’s own description, not a test we ran.

Sources: