CrewAI: Four Flaws Chain Prompt Injection Into a Shell - VU#221883, CVE-2026-2275 / 2285 / 2287
Four vulnerabilities in CrewAI - the open-source Python framework for multi-agent systems - can be chained via prompt injection into sandbox escape, remote code execution and arbitrary local file read. They were reported by Yarden Porat of Cyata, coordinated by CERT/CC as VU#221883, with an advisory from ThaiCERT on April 2, 2026. The most consequential is a silent fallback: when CrewAI's Code Interpreter cannot reach Docker it drops to SandboxPython, an insecure mode that permits code execution on the host - and it does not continuously verify that Docker is still running during execution. This advisory covers the chain, why *unsafe default* is the actual vulnerability, and what to check.
What happened
CrewAI's Code Interpreter is meant to run model-generated code inside Docker, which is the boundary between *the agent wrote some Python* and *the agent ran some Python on your host*. Three of the four issues are documented specifically:
| CVE | Issue |
|---|---|
| CVE-2026-2275 | The Code Interpreter tool falls back to SandboxPython when it cannot access Docker |
| CVE-2026-2287 | CrewAI does not continuously verify that Docker is running during execution, so the system defaults to an insecure sandbox mode that permits RCE |
| CVE-2026-2285 | Local file read in the JSON loader tool - no file path validation, so an attacker can read sensitive files directly from the server |
A fourth CVE is included in the CERT/CC note; the coordinated set spans RCE, SSRF and arbitrary local file read. Consult VU#221883 for the complete enumeration and affected version ranges rather than relying on a summary.
The two Code Interpreter issues are the interesting pair because they are the same mistake at two points in time. CVE-2026-2275 is the fallback existing at all: if Docker is unavailable, run the code anyway, less safely. CVE-2026-2287 is that the Docker check is not continuous - so it is not enough for Docker to be present at startup. An attacker who can cause Docker to become unreachable mid-execution, or who simply lands on a host where Docker is not running, gets the unsafe path. Together they mean the sandbox is best-effort, and best-effort containment is not containment.
The trigger is prompt injection. CrewAI agents read content - files, web pages, tool results - and content can carry instructions. So the attacker does not need to reach the framework's API. They need the agent to read something. That converts what would be a local misconfiguration into a remote, unauthenticated path to a shell on the host running the crew.
Why this is an agentic-endpoint risk
Research framing the 2026 disclosures as a cluster identifies one shared root cause: agent frameworks shipping with unsafe defaults that turn prompt injection from a model-level annoyance into a direct, unauthenticated shell on the host. That is the sentence to take away. The vulnerability is not that a sandbox had a bypass; it is that the framework chose to continue when the sandbox was unavailable, because failing the task felt worse than running it unsafely.
That decision recurs across this class. It is the same shape as the fail-open canonicalization in DuneSlide's CVE-2026-50549, where a path check that could not resolve its target trusted the unvalidated path. In both cases the check was present, correct, and defeated by its own error path. What does this control do when it cannot decide? is the single most productive question to ask of any agent harness, and *proceed* is the wrong answer with surprising frequency.
For a security team the operational problem is that CrewAI is a library, not an application. It arrives via pip install inside someone's project, runs on a developer laptop or a CI runner, and produces no inventory entry anywhere. There is no admin console listing your crews. Frameworks are part of the same discovery gap as agents and MCP servers - the eight AI artifact types Anomity inventories per endpoint - and they proliferate the way AI agents became the new shadow IT. We cover the broader picture in securing AI agent frameworks.
How Anomity surfaces and governs it
First, find where frameworks actually run. Anomity's unprivileged Endpoint Sensor runs on Windows, macOS and Linux and inventories AI agents, MCP servers, extensions, plugins, skills, secrets, hooks and CLIs across managed endpoints, so agent runtimes are visible artifacts rather than a dependency buried in someone's requirements.txt. "Which endpoints run a multi-agent framework, and does any of them lack a working sandbox?" is the question this advisory makes urgent.
Second, decide at the tool call. A sandbox that degrades silently cannot be the only boundary, and CrewAI's own fix cannot help a version you have not upgraded. Where an agent exposes a hook - for example the PreToolUse event in Claude Code - Anomity evaluates each call against policy and returns allow, deny, or log before it runs, so code execution, a credential read, or a file access outside the project meets a check that is independent of whether the framework's own sandbox is functioning. That independence is the point: runtime governance does not fail open when Docker does.
Third, keep the record. Artifact changes and policy decisions land in a queryable 90-day audit trail, giving a real exposure window rather than an estimate. Anomity collects metadata only, with on-endpoint secret redaction, is SOC 2 Type II, and complements EDR, DLP, network and GRC tooling. See how it works.
You can't govern what you can't see.The Anomity principle
What to check across your fleet
- Consult CERT/CC VU#221883 for the full CVE set and affected version ranges, and upgrade CrewAI accordingly - do not work from summaries, including this one.
- Find every place CrewAI is installed: developer laptops, CI runners, containers, and notebooks. It arrives as a library dependency, so search dependency manifests as well as endpoints.
- On each of those hosts, check whether Docker is actually available and running. The unsafe path is reached precisely where it is not, so a host without Docker is where the sandbox was never enforcing anything.
- Disable or restrict the Code Interpreter tool where crews do not genuinely need code execution. The most reliable mitigation for a degradable sandbox is not needing it.
- Audit the JSON loader and any other file-reading tool for path validation, and confirm the validation fails closed when resolution errors rather than trusting the path.
- Treat every content source a crew reads - files, web pages, tool results, other agents' output - as untrusted input, since prompt injection is the trigger for the whole chain.
- Scope the credentials available to crew processes. A framework process running with a broad cloud role or a developer's full shell environment hands its blast radius straight to an escape.
- Audit your own harnesses for controls that continue when they cannot verify. Ask what each check does when it fails, and make sure the answer is deny - see least privilege for AI agents and Claude Code permissions and hooks hardening.
The CrewAI set is worth reading as a design lesson rather than four bugs to patch. A sandbox that runs the code anyway when it cannot start the sandbox is a usability decision with a security consequence, and prompt injection is what makes that consequence remotely reachable. Upgrade per VU#221883, then go and ask which of your agent harnesses proceed when a check cannot be satisfied. For the framework-level picture see securing AI agent frameworks, for the same fail-open pattern in an IDE DuneSlide, and for lifecycle placement ADLC. To see where agent frameworks run across your fleet, request early access.
Frequently asked questions
What are the CrewAI vulnerabilities in VU#221883?
VU#221883 is the CERT/CC coordinated disclosure for four vulnerabilities in CrewAI, the open-source Python multi-agent framework, reported by Yarden Porat of Cyata and covered by a ThaiCERT advisory on April 2 2026. Three are documented specifically. CVE-2026-2275: the Code Interpreter tool falls back to SandboxPython when it cannot access Docker. CVE-2026-2287: CrewAI does not continuously verify that Docker is running during execution, so the system defaults to an insecure sandbox mode permitting remote code execution. CVE-2026-2285: the JSON loader tool lacks file path validation, allowing arbitrary local file read. The coordinated set spans RCE, SSRF and local file read, and can be chained together via prompt injection. Consult VU#221883 directly for the complete enumeration and affected versions.
Why is the Docker fallback the most serious issue?
Because it makes the sandbox best-effort, and best-effort containment is not containment. CrewAI's Code Interpreter is supposed to run model-generated code inside Docker, which is the boundary between the agent writing Python and the agent running Python on your host. CVE-2026-2275 means that if Docker is unavailable, the framework runs the code anyway in a less safe mode. CVE-2026-2287 means the Docker check is not continuous, so Docker being present at startup is not sufficient - an attacker who can make it unreachable mid-execution, or who simply lands on a host where it is not running, reaches the unsafe path. The two together are the same mistake at two points in time: continuing when the boundary cannot be established.
How does prompt injection turn this into a remote attack?
Without prompt injection these would be local misconfigurations requiring access to the framework's API. But CrewAI agents read content - files, web pages, tool results, and other agents' output - and content can carry instructions. So an attacker does not need to reach your framework; they need your agent to read something they control. That is what converts a degradable sandbox into a remote, unauthenticated path to a shell on the host running the crew. It is also why the mitigations that matter most are treating every content source as untrusted and enforcing a boundary that does not depend on the framework's own sandbox functioning.
What is the shared root cause across the 2026 framework disclosures?
Research framing these as a cluster identifies it as agent frameworks shipping with unsafe defaults that turn prompt injection from a model-level annoyance into a direct, unauthenticated shell on the host. The specific recurring pattern is the fail-open decision: a control exists, is correct in principle, and is defeated by its own error path because continuing felt preferable to failing the task. CrewAI runs code when it cannot start the sandbox. DuneSlide's CVE-2026-50549 in Cursor trusted an unvalidated path when symlink resolution failed. The productive question for any agent harness is what a control does when it cannot decide, and proceed is the wrong answer far more often than it should be.
How do we find where CrewAI is running?
This is genuinely harder than for a product, because CrewAI is a library rather than an application. It arrives through pip install inside someone's project and runs on developer laptops, CI runners, containers and notebooks, producing no inventory entry and no admin console listing your crews. So search dependency manifests across repositories as well as inventorying endpoints, and check both. Then, on each host you find, verify whether Docker is actually available and running - a host without it is precisely where the sandbox has never been enforcing anything, which makes it the first place to look rather than the last.
What mitigations work if we cannot upgrade immediately?
Four help materially. Disable or restrict the Code Interpreter tool where crews do not genuinely need code execution, since not needing a degradable sandbox is the most reliable mitigation. Ensure Docker is present and running on every host that does use it, closing the path to the unsafe fallback. Scope the credentials available to crew processes, because a framework running with a broad cloud role or a developer's full shell environment hands its blast radius directly to any escape. And enforce a boundary outside the framework - evaluating tool calls against policy and returning allow, deny or log - so that code execution or a credential read meets a check that does not fail open when Docker does.




