harness
1. noun: a deterministic program that wraps a model, constructs and manages its context, and mediates the model's inputs and outputs with the surrounding environment (e.g. the OS, tools, files, network, or user).
Every issue on this page happened on the far side of a harness.
Meaning any and all harnesses. When a harness delegates a decision to a model, that decision is no longer deterministic.
fails
1. verb · third person singular present of fail: to not do what it exists to do, or what it is expected to do.
When the harness fails, restricted files enter model context.
2. noun informal · plural of fail: cases of failing.
This page is a collection of harness fails.
Both readings are intended. Sometimes the harness broke; sometimes it was never there.
Motivation
Agent tools can be great multipliers in the right hands. Today's harnesses, however, often pose a security risk to their users. For two decades, the industry moved toward least privilege: apps were increasingly sandboxed and had to ask permission before accessing our personal data. Developer tools were largely the exception, but their failures were as deterministic as the tools themselves. Agent tools have changed the developer landscape: the same multiplier applies to the risk too.
Permission policies are often inadequate, and fail at the very thing they were designed to do. The resulting issues are usually framed by their outcomes and rarely by their root cause, leaving the underlying problem obscured. A problem without a name or a clear definition is hard to discuss and even harder to fix.
With the agentaccess.txt specification, my goal is to propose how file-access policy could be declared in the filesystem and how a harness should enforce it. The record collects documented cases where harnesses failed, and the matrix scores harnesses against abstract requirements derived from the specification.
We must standardize these expectations, so our tools can earn the trust we already give them.
Contents
The record
Some frameworks assume a bad actor and classify the attack (how it is built, what it wants); others classify the harm (what went wrong in the world). harness.fail classifies the failure: the boundary the harness itself was supposed to hold, but didn't, regardless of intent. That is why two of the seven classes, Scaffolding collapse and Ambient activation, have no direct counterpart in OWASP or MITRE ATLAS. These seven classes begin where the harness makes the decision and move outward, through what the agent reads, the tools it connects and the instructions it trusts, to the workspace it opens and the software it was installed from. The last, Excessive agency, is the quietest: every check passes, and the agent does damage anyway with the reach it was given.
Scaffolding collapse
Term introduced here by Peter Seprus, 2026.
Enforcement bugs in non-malicious tools. The tool declares a boundary (a sandbox, a path restriction, an ignore rule, an approval prompt, an access check) and its own code fails to enforce it, so the boundary it promises is not the boundary it enforces. The test: the issue would not exist if the tool enforced exactly what it documents. How the gap is reached does not matter; an injected instruction, a malicious repository and a curious model all count. Scaffolding is the usual word for the code around a model, and here it is that code that gives way. The harness is the bug.
No direct mapping in OWASP or MITRE ATLAS.
37 issues
| Issue | Date | Harness | The fail | Fix |
|---|---|---|---|---|
| DeepSeek Harness sandbox escape (CVE-2026-82533, OX Research) | 2026 | DeepSeek Harness | The local agent-control API trusted a client-supplied loopback Host header instead of the connection's real origin, so a sandboxed tool process could call it over loopback to switch its own session to danger-full-access and disable the approval prompt. | Fixed in 0.1.2-alpha.1, August 27, 2026. |
| GitSpawn (named by Manifold Security; CVE-2026-71963, Francisco Rosales (Manifold Security); CVE-2026-72718, assigned after Manifold's report; CVE-2026-19592, Fudan University System Software and Security Lab and Doyensec via ZDI) | 2026 | Claude Code, OpenAI Codex CLI, OpenAI Codex Desktop, Cursor, goose, Grok Build, Hermes Agent, Qwen Code | Agents ran git in the background to gather context, outside their sandboxes and without an approval prompt, on some agents before the workspace-trust prompt, so a repository whose .git/config set core.fsmonitor executed an attacker-chosen command on the host. An ordinary git clone does not carry the source's .git/config, so the repository has to arrive with it intact, for example as an archive or a copied folder. | Fixed in OpenAI Codex CLI 0.131.0, Codex Desktop 26.519, goose 1.44.0 and Hermes Agent commit f6234d0; Claude Code fixed the core.fsmonitor path by 2.1.196 and Cursor patched, per Manifold; Claude Code's ultrareview, Grok Build and Qwen Code unpatched as of September 1, 2026. |
| IDEsaster (Ari Marzouk (MaccariTA), 24 CVEs across vendors) | 2025 | GitHub Copilot, Cursor, Windsurf, Kiro, Zed, JetBrains Junie, Roo Code, Cline, Gemini CLI, Claude Code | Injected instructions made agents use ordinary file writes to trigger base-IDE features: a JSON file whose remote $schema URL the IDE fetched, leaking data, and edits to IDE settings (.vscode/settings.json, JetBrains workspace files, .code-workspace) that pointed executable paths at attacker files, running code. | Fixed per vendor, some without a CVE; Anthropic acknowledged the issue and answered with a security warning. |
| Caught in the Hook (CVE-2025-59536, CVE-2026-21852, named by Check Point Research) | 2025 | Claude Code | A cloned repository's .claude/settings.json started its MCP servers and redirected ANTHROPIC_BASE_URL before the trust dialog was answered, running commands and sending the API key to the attacker's server. Repository hooks also ran after trust without the dialog mentioning them. | Fixed in Claude Code v1.0.87, v1.0.111 and v2.0.65. |
| Copilot YOLO-mode remote code execution (CVE-2025-53773, Johann Rehberger; found in parallel by Persistent Security and Ari Marzouk) | 2025 | GitHub Copilot | A prompt injection made the agent write "chat.tools.autoApprove": true into .vscode/settings.json, which it could do without approval, turning off every confirmation before it ran shell commands. | Fixed in Microsoft's August 2025 Patch Tuesday. |
| CurXecute (CVE-2025-54135, named by Aim Security) | 2025 | Cursor | A prompt injection in a Slack message, fetched through the Slack MCP server, made the agent suggest an edit to ~/.cursor/mcp.json; the edit was written to disk before the user could approve or reject it, and Cursor started the new server at once, running the attacker's command. | Fixed in Cursor 1.3.9. |
| EscapeRoute (CVE-2025-53109, CVE-2025-53110, named by Cymulate) | 2025 | Anthropic Filesystem MCP server | A prefix check let paths that merely began with an allowed directory's name pass as inside it, and symlinks within allowed directories reached files outside them. | Patched July 1, 2025 (reported March 30), in 2025.7.01; the advisories also list 0.6.3, the CVE records 0.6.4. |
| Docker Sandboxes escapes (CVE-2026-77179, Accomplish; CVE-2026-79994, ThreatNotify) | 2026 | Docker Sandboxes | The macOS virtio-fs host server followed symlinks when reopening an unlinked file from a stored path, and the guest-to-host Unix socket relay validated a socket path but reconnected by pathname, so a malicious guest could swap in a symlink and reach host files or arbitrary host sockets outside the shared workspace. | Fixed in Docker Sandboxes 0.42.0, September 7, 2026. |
| Heapjack and Overpatch (Accomplish) | 2026 | OpenAI Codex CLI, OpenAI Codex Desktop | Codex CLI's apply_patch granted write access to the parent folders of paths in a patch, so a patch referencing /tmp gained write access to / without an approval prompt (Overpatch); Codex Desktop's node_repl kept trusted and untrusted V8 contexts in one heap, so untrusted code could read the authorization token and run unsandboxed commands even in read-only mode (Heapjack). | Fixed within eight days of the August 12, 2026 report: Codex CLI 0.149.0, and Codex Desktop build 26.818.21641 per the Cloud Security Alliance. |
| Cursor CLI pre-trust worktree execution (Manifold Security) | 2026 | Cursor CLI | In worktree mode, the setup-worktree command from a git-tracked .cursor/worktrees.json ran through sh -c before the Workspace Trust prompt, under a hardcoded no-sandbox policy that --sandbox enabled did not override. | Pre-trust execution fixed in cursor-agent 2026.07.23-e383d2b, per Manifold; the setup command still runs unsandboxed regardless of --sandbox enabled. Cursor closed the report as informative, disputing that workspace trust was bypassed. |
| Cursor Cloud Agent browser sandbox escape (CVE-2026-61613, Arbër Salihi) | 2026 | Cursor Cloud Agent | In browser-enabled sessions, attacker-controlled web content connected from inside the agent container to a local agent endpoint that had no authentication, giving code execution in the sandbox and the session's files, credentials and GitHub App tokens. | Fixed in the Cursor Cloud Agent environment, March 31, 2026; no user action required. |
| Cursor sandbox escapes (CVE-2026-50548, CVE-2026-50549, Cato AI Labs (named DuneSlide)) | 2026 | Cursor | Prompt injection could make the agent write outside the project, by pointing the terminal tool's working-directory parameter elsewhere or by forcing a path-canonicalization fallback through a symlink, and overwriting the cursorsandbox helper turned this into a sandbox escape with remote code execution. | Fixed in Cursor 3.0. |
| Gemini CLI --yolo allowlist bypass (Novee Security and Pillar Security) | 2026 | Gemini CLI | Under --yolo, Gemini CLI ignored the fine-grained tool allowlist, so run_shell_command(echo) allowed any command. In headless mode it also trusted the folder automatically and loaded environment variables from the local .gemini/ directory. | Fixed in Gemini CLI 0.39.1 and run-gemini-cli 0.1.22. |
| Antigravity Secure Mode bypass (Pillar Security) | 2026 | Google Antigravity | The find_by_name tool passed its pattern straight to fd, so the pattern -Xsh ran a staged script. The native tool fired before Secure Mode's sandbox and command checks ever saw the call. | Google marked it fixed on February 28, 2026. |
| Deny rules skipped past 50 subcommands (Adversa AI) | 2026 | Claude Code | A shell command chaining more than 50 subcommands hit an analysis cap, after which Claude Code skipped its deny-rule checks and fell back to a generic approval prompt, auto-approved in automated runs, so a denied command could run once padded with 50 harmless statements. | Adversa reports it as apparently fixed in Claude Code v2.1.90; no Anthropic advisory or changelog entry confirms it. |
| ShadowPrompt (named by Koi Security) | 2026 | Claude in Chrome | The extension accepted prompts from any *.claude.ai page, and an XSS on a-cdn.claude.ai let any website send it instructions with zero clicks. | Fixed in 1.0.41 with a strict origin check; the XSS was fixed on February 19, 2026. |
| Shell-allowlist expansion bypasses (CVE-2026-44462, CVE-2026-44463, CVE-2026-44466, CVE-2026-29783; Zed and GitHub advisories) | 2026 | Zed, GitHub Copilot CLI | Regex allow rules such as ^git\b were beaten with PAGER=curl git diff, ${var@P} and $(($(cmd))). Copilot CLI's read-only classifier was fooled by the same kind of parameter-transformation expansion. | Fixed in Zed 0.229.0 and Copilot CLI 0.0.423. |
| Cursor sandbox escapes through deferred execution (CVE-2026-26268, CVE-2026-48124, CVE-2026-73217, CVE-2026-73218; Novee, NVIDIA AI Red Team and others) | 2026 | Cursor | Inside the auto-run sandbox the agent could write files that later ran outside it (git hooks, a .claude/settings.local.json hook, a virtualenv interpreter the Python extension invokes) or, with Docker Desktop and the Dev Containers CLI, start a privileged container that mounts Docker's virtiofs0, exposing the home directory. | Fixed in Cursor 2.5, 3.0.0 and 3.1.2. |
| Claude Code sandbox escapes (CVE-2026-25725, CVE-2026-39861, CVE-2026-55607, via HackerOne) | 2026 | Claude Code | Sandboxed code planted SessionStart hooks in a not-yet-existing .claude/settings.json that ran on the host at the next start. Symlinks made inside the sandbox were followed by the unsandboxed app, and a worktree named .git with git fsmonitor overwrote ~/.zshenv. | Fixed in Claude Code v2.1.2, v2.1.64 and v2.1.163. |
| Claude Code WebFetch allowlist exfiltration (CVE-2026-24052, CVE-2026-54316; reported via HackerOne by 47sid-praetorian and novee) | 2026 | Claude Code | A prefix check let modelcontextprotocol.io.example.com pass as an allowlisted domain, and the pre-approved huggingface.co served as a covert channel for data. | Fixed in Claude Code v1.0.111 and v2.1.163. |
| OpenClaw approval takeover (CVE-2026-25253, CVE-2026-41349; depthfirst and others) | 2026 | OpenClaw | A gatewayUrl query parameter made the UI send its auth token to an attacker, who used the harness's own API to switch off exec approval and move execution out of the container. A later advisory showed the model itself could call config.patch to turn approval off. | Fixed in OpenClaw 2026.1.29 and 2026.3.28. |
| Anthropic Git MCP server chain (CVE-2025-68143, CVE-2025-68144, CVE-2025-68145, Cyata) | 2025 | Anthropic Git MCP server | The server did not enforce its --repository restriction per call, git_init worked on any directory, and git_diff --output= overwrote files. Chained with the filesystem server, a prompt injection reached code execution through Git's smudge and clean filters (Cyata, via The Register). | Fixed in mcp-server-git 2025.9.25 (git_init removed) and 2025.12.18. |
| Plan Mode destructive commands (Cursor forum) | 2025 | Cursor | In what the user reports was mostly Plan Mode, the agent deleted about 70 git-tracked files with rm -rf and made commits; after the user wrote "DO NOT RUN ANYTHING", it ran pkill and started processes. Cursor staff called it a violation of Plan Mode's read-only constraint and a critical bug in Plan Mode constraint enforcement. | — |
| PromptJacking (named by Koi Security) | 2025 | Claude Desktop | Three official Claude Desktop extensions (Chrome, iMessage, Apple Notes) passed input straight into AppleScript without escaping, so a web page could turn an ordinary question into shell commands on the host. | Fixed in extension version 0.1.9. |
| Cursorignore bypass (CVE-2025-64110, joaodunas and aretekzs (Cursor advisory)) | 2025 | Cursor | An agent steered by prompt injection could write a new .cursorignore that invalidated the existing ones, then read the files they protected. | Fixed in Cursor 2.0, which blocks the agent from creating or editing .cursorignore files. |
| Copilot sensitive-file guard bypasses (CVE-2025-62222, CVE-2025-62449, CVE-2026-21523, CVE-2026-41109, CVE-2026-70335; Microsoft advisories) | 2025 | GitHub Copilot, VS Code | After CVE-2025-53773, the guard that asks before the agent edits .vscode/settings.json and similar files was bypassed again and again: by casing, by creating a file instead of editing it, by apply_patch path "healing", and by writing custom-agent files that carry hooks. | Fixed in Copilot Chat 0.32.1, 0.32.5 and 0.37.3, and VS Code 1.119.1 and 1.132.1. |
| Claude Code deny-rule bypass through symlinks (CVE-2025-59829, CVE-2026-25724, via HackerOne) | 2025 | Claude Code | A file denied in settings, such as /etc/passwd, could be read through a symlink pointing to it. The first fix regressed and needed a second CVE. | Fixed in Claude Code v1.0.120, and again in v2.1.7. |
| Claude Code trust-dialog bypasses (CVE-2025-59041, CVE-2025-59828, CVE-2025-65099, CVE-2026-33068, CVE-2026-40068; NVIDIA AI Red Team, Redguard AG and others) | 2025 | Claude Code | Before the trust dialog was answered, code could run through a maliciously configured git config user.email or through Yarn plugins. A committed defaultMode: bypassPermissions skipped the dialog outright, and a spoofed worktree commondir pointing at an already-trusted path skipped it too. | Fixed in Claude Code v1.0.39, v1.0.105, v2.1.53 and v2.1.84. |
| Claude Code command-validation bypasses (CVE-2025-58764, CVE-2025-64755, CVE-2025-66032, CVE-2026-24053, CVE-2026-24887, CVE-2026-25722, CVE-2026-25723; GMO Flatt Security, SpecterOps and others) | 2025 | Claude Code | Gaps in the command parser turned auto-approved read-only commands into code execution or writes to protected folders or outside the project, without a prompt: man --html, sort --compress-program, sed's e command, $IFS and @P expansions, zsh >|, and cd into .claude. | Fixed across Claude Code v1.0.93 to v2.0.74. |
| Kiro trusted-commands self-allowlisting (Johann Rehberger) | 2025 | Kiro | A prompt injection made the agent write "kiroAgent.trustedCommands": ["*"] into .vscode/settings.json, or add a server to .kiro/settings/mcp.json, without approval, then run any command. | Fixed in Kiro 0.1.42. |
| Amazon Q find -exec read-only bypass (Johann Rehberger) | 2025 | Amazon Q Developer | find was classed as read-only and skipped confirmation, so a prompt injection in a source comment ran find -exec with arbitrary commands. | Fixed in v1.85, which reclassified find. |
| Codex CLI sandbox-root escapes (CVE-2025-55345, CVE-2025-59532; JFrog and Tzanko Matev) | 2025 | OpenAI Codex CLI | An AGENTS.md injection plus an in-repo symlink sent --full-auto writes outside the working directory, and the sandbox treated a model-chosen working directory as its writable root. | Fixed in Codex CLI 0.12.0 and 0.39.0. |
| Zed project settings auto-execution (CVE-2025-55012, CVE-2025-68432, CVE-2025-68433; Ari Marzouk, Aaron Portnoy (Mindgard)) | 2025 | Zed | A repository's .zed/settings.json could define MCP and language servers that ran commands when the project opened, with no interaction, and the agent could write project config past its permission checks. | Fixed in Zed 0.197.3 and 0.218.2-pre. |
| Cursor sensitive-file protection bypasses (CVE-2025-54130, CVE-2025-59944, CVE-2025-61593, CVE-2025-64107, CVE-2025-64108; Lakera and others) | 2025 | Cursor, Cursor CLI | The approval guard on .cursor/mcp.json, cli.json and .vscode/settings.json was bypassed through case-insensitive filesystems, Windows backslashes, NTFS short names and alternate data streams, and by creating the file instead of editing it. Each bypass could lead to code execution. | Fixed in Cursor 1.3.9, 1.7 and 2.0, and Cursor CLI 2025.09.17. |
| InversePrompt path-restriction bypass (CVE-2025-54794, CVE-2025-54795, named by Cymulate) | 2025 | Claude Code | Prefix matching instead of canonical path comparison let a sibling directory that shared the working directory's prefix, such as claude_code_evil next to claude_code, pass as inside it. A second flaw in command parsing let an untrusted command run past the confirmation prompt. | Fixed in Claude Code v0.2.111 and v1.0.20. |
| Cursor auto-run allowlist bypasses (CVE-2025-54131, CVE-2026-22708, CVE-2026-31854; Backslash Security, Pillar Security and others) | 2025 | Cursor | Cursor's auto-run denylist was evaded with base64, subshells, scripts and quoting, its allowlist with backticks and $(), and shell built-ins like export poisoned environment variables that allowlisted commands then used. | Denylist deprecated in Cursor 1.3; fixes in 1.3, 2.0 and 2.3. |
| Unauthenticated local agent servers (CVE-2025-52882; CVE-2026-22812, reported by CyberShadow; CVE-2026-44211, reported by sagilayani) | 2025 | Claude Code, OpenCode, Cline | Agents started local servers without authentication (a WebSocket in the Claude Code IDE extension, an HTTP server with permissive CORS in OpenCode, a WebSocket in Cline Kanban), so a website could read files (Claude Code), run shell commands (OpenCode) or inject prompts into agent terminals (Cline). | Fixed in the Claude Code IDE extension 1.0.24 and OpenCode 1.0.216; the Cline advisory (2.13.0 and earlier) listed no patch when it was published. |
Indirect prompt injection
Term introduced by Greshake et al., 2023, extending prompt injection (Simon Willison, 2022).
“We reveal new attack vectors, using Indirect Prompt Injection, that enable adversaries to remotely (without a direct interface) exploit LLM-integrated applications by strategically injecting prompts into data likely to be retrieved.”
Malicious instructions arrive inside material the agent legitimately processes, such as a README, a GitHub issue, a web page or a tool result, and steer the agent into acting for the attacker: leaking files, secrets or credentials, running attacker code, or handing over control of its machine.
OWASP: Prompt Injection (LLM01:2025), Sensitive Information Disclosure (LLM02:2025), Agent Goal Hijack (ASI01), Tool Misuse and Exploitation (ASI02) · MITRE ATLAS: LLM Prompt Injection: Indirect (AML.T0051.001), Exfiltration via AI Agent Tool Invocation (AML.T0086), LLM Response Rendering (AML.T0077)
15 issues
| Issue | Date | Harness | The fail | Fix |
|---|---|---|---|---|
| Comment and Control (Aonan Guan, Zhengyu Liu, Gavin Zhong) | 2026 | Claude Code, Gemini CLI, GitHub Copilot | Pull request titles, issue comments and hidden HTML comments in issues made the agents running in GitHub Actions read the runner's environment and post its API keys and tokens back to the repository, past Copilot's environment filtering, secret scanning and network firewall. | Anthropic blocked ps in the Claude Code Security Review action and said it “is not designed to be hardened against prompt injection”; GitHub called the Copilot exposure “a previously identified architectural limitation”; no Gemini CLI fix stated. |
| Claude Desktop Extensions zero-click RCE (LayerX) | 2026 | Claude Desktop | Asked to “take care of” the latest Google Calendar events, Claude followed a malicious event and chained a low-risk connector into an unsandboxed local extension that downloaded and ran attacker code, without asking the user. | LayerX reported it; Anthropic decided not to fix it at the time. |
| Claude Cowork file exfiltration (PromptArmor) | 2026 | Claude Cowork | Hidden text in a .docx made the agent curl the user's files to Anthropic's file upload API under the attacker's API key. The domain was on the egress allowlist, so the network restriction did not stop it. | — (not remediated at the time of disclosure) |
| Antigravity exfiltration (PromptArmor) | 2025 | Google Antigravity | Injection hidden in a web page drove the agent to read a project's .env with a shell command that bypassed the tool's own .gitignore-based protection for that file, then exfiltrate the credentials through an allowlisted domain. | — (not reported: PromptArmor skipped disclosure because Google had said it was already aware of data-exfiltration risks) |
| CamoLeak (Omer Mayraz, Legit Security) | 2025 | GitHub Copilot | A hidden comment in a pull request description made Copilot Chat spell out the victim's private-repository contents as a sequence of pre-signed Camo image URLs, which the browser fetched through GitHub's own image proxy, past its Content Security Policy. | Fixed server-side by GitHub, August 14, 2025, by disabling image rendering in Copilot Chat. |
| Cursor Mermaid exfiltration (CVE-2025-54132, Johann Rehberger and MaccariTA) | 2025 | Cursor | An injection in a source-code comment made the agent collect API keys from the project, then render a Mermaid diagram whose image URL carried them to the attacker's server, with no confirmation. | Fixed in Cursor 1.3, July 2025 (GHSA-43wj-mwcc-x93p). |
| Gemini CLI hijack (Tracebit) | 2025 | Gemini CLI | Instructions hidden in a README, a flaw in matching commands against the allowlist and a display flaw that hid everything after a run of whitespace let a malicious command run as a user-allowlisted grep without being shown, executing arbitrary code; the demo sent environment variables to a remote server. | Fixed in v0.1.14, July 25, 2025 — 28 days after report. |
| Codex Desktop image exfiltration (CVE-2026-14898; Johann Rehberger, Itay Ravia (Cato Networks)) | 2026 | OpenAI Codex Desktop | An indirect injection made the model build an image URL carrying secrets, which the app fetched automatically. | Fixed in 26.527.31326. |
| Manus VS Code exposure (Johann Rehberger) | 2025 | Manus | An injection in a document made the agent publish its VS Code server to the internet with its port-exposure tool, which asks for no approval, then browse to an attacker URL that carried the server address and password; rendered images leaked data as well. | — (reported June 2025; mitigation status unclear at publication) |
| Windsurf exfiltration (Johann Rehberger) | 2025 | Windsurf | An injection in a file under analysis made the agent read .env and send it out through read_url_content, which fetches URLs without approval, or through an auto-rendered image. | — (unfixed at publication, August 2025; Windsurf later said fixes were in progress, with no date) |
| Jules exfiltration and ZombAI (Johann Rehberger) | 2025 | Google Jules | Instructions in a GitHub issue made the agent leak data through rendered images and its browsing tool. In follow-up posts, it downloaded and ran a command-and-control implant on its machine, which had unrestricted internet access, and invisible Unicode tag characters in an issue made it add backdoor code and run it. | — (reported May–June 2025; not fully mitigated at publication, per the researcher) |
| Claude Code DNS exfiltration (CVE-2025-55284, Johann Rehberger) | 2025 | Claude Code | An injection in a file under analysis made the agent read .env and put the key into a hostname for ping, which the default allowlist ran without approval, so the DNS lookup carried it to the attacker's server. | Fixed in Claude Code 1.0.4, June 2025 (GHSA-x5gv-jw7f-j6xj). |
| OpenHands ZombAI (Johann Rehberger) | 2025 | OpenHands | Instructions on a web page or in a GitHub issue made the agent download and run malware that connected to the attacker's command-and-control server. | — (reported March 2025; no fix stated at publication) |
| Devin secret leaks (Johann Rehberger) | 2025 | Devin | An injection in content such as a GitHub issue made the agent read secrets exposed to it as environment variables and send them out through its shell, its browser or a rendered markdown image. | — (reported April 2025; fix status unanswered at publication) |
| Codex cloud ZombAI (Johann Rehberger) | 2025 | OpenAI Codex cloud | Instructions planted in a GitHub issue made the agent download and run malware that joined the attacker's command-and-control server, reached through a cloudapp.azure.com host that the azure.com entry in the Common Dependencies network allowlist let through. | None — OpenAI closed the report as not applicable the day it was filed, June 10, 2025. |
Tool poisoning
Term introduced by Invariant Labs, 2025 for poisoned tool descriptions; used here for every way a hostile tool reaches the agent.
The tool channel itself is hostile: instructions ride in tool descriptions or results, or the agent is steered into configuration writes that escalate to code execution.
OWASP: Supply Chain (LLM03:2025), Prompt Injection (LLM01:2025), Agentic Supply Chain Vulnerabilities (ASI04), Tool Misuse and Exploitation (ASI02) · MITRE ATLAS: AI Agent Tool Poisoning (AML.T0110), AI Supply Chain Compromise: AI Agent Tool (AML.T0010.005), AI Supply Chain Rug Pull (AML.T0109)
5 issues
| Issue | Date | Harness | The fail | Fix |
|---|---|---|---|---|
| GhostSplice (named by ASSET Research Group (Murali Ediga, Johnny Dao, Sudipta Chattopadhyay)) | 2026 | Cursor, OpenAI Codex CLI, GitHub Copilot | Instructions fragmented across MCP tool descriptions and tool results raised average compliance across eleven models from 42% to 82% through the model APIs, with no fragment looking malicious on its own; a three-fragment version also worked inside Cursor, Codex CLI and VS Code with GitHub Copilot. | — (disclosed to the vendors; only OpenAI replied, calling it third-party MCP risk) |
| Windsurf zero-click MCP config rewrite (CVE-2026-30615, OX Security) | 2026 | Windsurf | Injected HTML content made Windsurf rewrite its local MCP config and register a malicious stdio server, with no user interaction. | — (no fixed version found) |
| MCPoison (CVE-2025-54136, named by Check Point) | 2025 | Cursor | An approved MCP configuration could be silently swapped afterward. | Fixed in Cursor 1.3, July 29, 2025. |
| WhatsApp MCP exfiltration (Invariant Labs) | 2025 | Cursor | A sleeper MCP server, once approved, swapped in a tool description that redirected the trusted WhatsApp server's messages to the attacker's number with the chat history attached; the confirmation dialog hid the payload off-screen. | — (research demonstration) |
| Tool Poisoning Attacks (named by Invariant Labs) | 2025 | Cursor | Hidden instructions in a malicious MCP server's tool description made the agent read ~/.cursor/mcp.json and ~/.ssh/id_rsa and pass them to the server as a tool-call argument. | — (research demonstration) |
Agent instruction-file injection
Term as used in the Arcanum Prompt Injection Taxonomy (Jason Haddix, Arcanum Information Security), which also lists Pillar Security's Rules File Backdoor.
Instruction files the agent trusts are themselves the injection vector.
OWASP: Prompt Injection (LLM01:2025), Supply Chain (LLM03:2025), Agent Goal Hijack (ASI01), Memory & Context Poisoning (ASI06) · MITRE ATLAS: Modify AI Agent Configuration (AML.T0081), AI Agent Context Poisoning (AML.T0080), AI Supply Chain Compromise: AI Software (AML.T0010.001)
3 issues
| Issue | Date | Harness | The fail | Fix |
|---|---|---|---|---|
| Forced Descent (named by Mindgard) | 2025 | Google Antigravity | A malicious .agent rules file made the agent write the global ~/.gemini/antigravity/mcp_config.json, even with non-workspace file access off, planting code that ran on every launch and survived a reinstall. | Google first closed the report as Won't Fix (Intended Behavior), reopened it after Mindgard's rebuttal, and on November 25, 2025 filed a bug with the product team; no fix has been announced. |
| .clinerules switches off approval (Mindgard) | 2025 | Cline | Markdown in a repository's .clinerules told the agent to set requires_approval=false, and commands then ran without consent. | No longer reproducible in Cline 3.35.0; Cline acknowledged the report but did not confirm a fix. |
| Rules File Backdoor (named by Pillar Security) | 2025 | Cursor, GitHub Copilot | Malicious instructions were hidden in rules files behind zero-width and bidirectional Unicode characters, invisible in review. | None in the agents — both vendors declined to treat it as a vulnerability, placing the burden on users; GitHub later added a hidden-Unicode warning on github.com (May 1, 2025). |
Ambient activation
Term introduced here by Peter Seprus, after ambient authority in capability-based security.
Opening a folder is enough. The agent, or the editor around it, starts acting on the project before the user has expressed any intent or granted trust: indexing it, or running the servers, tasks and settings the repository defines.
No direct mapping in OWASP or MITRE ATLAS.
3 issues
| Issue | Date | Harness | The fail | Fix |
|---|---|---|---|---|
| Codex CLI project MCP config execution (CVE-2025-61260, Check Point Research) | 2025 | OpenAI Codex CLI | A repository .env set CODEX_HOME=./.codex, so Codex loaded the repository's own config.toml and started its MCP server commands at launch, with no approval. | Fixed in Codex CLI 0.23.0, August 20, 2025, per Check Point; the CVE record lists 0.23.0 and earlier as affected. |
| Cursor CLI repository config execution (CVE-2025-61592, Assaf Levkovich (JFrog); CVE-2025-64109, avivdon) | 2025 | Cursor CLI | A project-local .cursor/cli.json could set the shell allowlist, and a repository's .cursor/mcp.json server ran when the CLI started, with no warning. | Fixed in Cursor CLI 2025.09.17. |
| Open Repo, Get Pwned (Oasis Security) | 2025 | Cursor | Cursor ships with Workspace Trust off, so a repository's .vscode/tasks.json with runOn: "folderOpen" ran as soon as the folder was opened. | Not changed; Cursor pointed users to enabling Workspace Trust. |
Supply-chain compromise
Generic industry term.
The software supply chain delivers the attack, and an agent harness is part of it: a harness release ships hostile, or a malicious package drives the agent the user already installed, or plants itself in that agent's configuration. The test: the harness is the payload, the weapon or the foothold.
OWASP: Supply Chain (LLM03:2025), Agentic Supply Chain Vulnerabilities (ASI04), Tool Misuse and Exploitation (ASI02) · MITRE ATLAS: AI Supply Chain Compromise: AI Software (AML.T0010.001), Deploy AI Agent (AML.T0103), User Execution: Malicious Package (AML.T0011.001)
4 issues
| Issue | Date | Harness | The fail | Fix |
|---|---|---|---|---|
| Mini Shai-Hulud (StepSecurity) | 2026 | Claude Code, VS Code | An npm worm committed a SessionStart hook in .claude/settings.json and a folderOpen task in .vscode/tasks.json into every repository it could reach, so opening any of them in either tool re-ran its payload. | — |
| Clinejection and the unauthorized cline@2.3.0 (Adnan Khan) | 2026 | Cline CLI | A prompt injection in Cline's AI issue-triage workflow, followed by Actions cache poisoning, leaked its publish tokens. Cline's rotation missed the npm token, and a third party then shipped cline@2.3.0, whose postinstall script installed OpenClaw on users' machines. | Fixed in 2.4.0; publishing moved to OIDC. |
| nx "s1ngularity" compromise (Nx postmortem; agent flags documented by Snyk) | 2025 | Claude Code, Gemini CLI, Amazon Q Developer CLI | Malicious nx releases, published with a stolen npm token, ran a postinstall script that invoked the victim's own AI CLIs with their safety switches off (--dangerously-skip-permissions, --yolo, --trust-all-tools) to inventory files holding secrets. | Malicious versions removed from npm the same day; Nx moved publishing to npm Trusted Publishing with 2FA. |
| Amazon Q Developer VS Code extension v1.84.0 (CVE-2025-8217, AWS bulletin) | 2025 | Amazon Q Developer | An attacker used an inappropriately scoped GitHub token to commit malicious code, designed to call the Q Developer CLI, into the extension's repository, and it shipped in release 1.84.0. A syntax error kept it from succeeding. | v1.85.0 released; v1.84.0 pulled from distribution. |
Excessive agency
Term from the OWASP Top 10 for LLM Applications (LLM06:2025), used here for its accidental case: no attacker, no injection.
No attacker and no injection: a conforming agent, acting on a benign instruction, deletes or overwrites data through its own error.
OWASP: Excessive Agency (LLM06:2025), Rogue Agents (ASI10) · MITRE ATLAS: no direct mapping
7 issues
| Issue | Date | Harness | The fail |
|---|---|---|---|
| PocketOS production-database deletion (Jer Crane) | 2026 | Cursor | Stuck on a credential mismatch in staging, the agent found an unscoped Railway token in an unrelated file and used it in one API call that deleted the production volume and its backups in nine seconds. |
| Claude Code archive deletion (GitHub issue) | 2026 | Claude Code | After moving about 1,500 images (around 50 GB) into a subfolder, the agent ran rm -rf on the parent folder, deleting the files it had just moved, without warning. |
| DataTalksClub terraform destroy (Alexey Grigorev) | 2026 | Claude Code | Working from a stale Terraform state, the agent ran terraform destroy against production (database, network, containers and snapshots, 1.94 million rows), and the user let it run. |
| Claude file-cleanup deletion (Nick Davidov) | 2026 | Claude Cowork | The agent tried renaming a folder and instead deleted one holding 15 years of the user's wife's camera photos. It ran through the terminal, so nothing went to the Trash; the files were later recovered from iCloud. |
| Claude Code home-directory wipe (u/LovesWorkin on Reddit) | 2025 | Claude Code | A repository-cleanup task produced an rm -rf whose trailing ~/ expanded to the user's entire home directory. |
| Antigravity D: drive wipe (u/Deep-Hyena492 on Reddit) | 2025 | Google Antigravity | Asked to clear a project cache in Turbo mode, which needs no approval, the agent deleted the root of the user's D: drive, bypassing the Recycle Bin. |
| Replit Agent production-database deletion (Jason Lemkin) | 2025 | Replit Agent | During an explicit code and action freeze, the agent deleted SaaStr's live production records for over 1,200 executives and over 1,190 companies, by the agent's own account. |
The matrix
The capabilities a harness would need to enforce a file-access policy, as derived from the agentaccess.txt specification and written as abstract requirements, grouped under four questions: can the user state a file-access policy, what do its rules actually gate, which way do its errors fail, and does the mechanism hold? Each harness is scored against them from its own documentation, source code, issue tracker and security advisories. A ? means no authoritative statement was found either way, and an undocumented boundary is itself a finding.
The requirements
Each requirement links to the specification section it derives from. The specification is one proposal for satisfying them; the requirements stand on their own.
A. Declarative surface — can the user state the policy?
- A1 Path rules
- User-authorable file-access rules exist at all: an ignore file, deny globs, private-file patterns. §1
- A2 Tree-resident
- The rules live in the directory they govern and travel with it — clone the tree, keep the policy. Any directory can carry its own policy file, applied by the path being accessed; a single project-root file, or one chosen by where the session starts, is partial. §4
- A3 Per-path
- Rules distinguish paths by pattern, not only whole-project switches. §5
- A4 Per-agent
- Rules can name which tool they bind — "tool X may work here, tool Y may not" — and a tool the rules do not name is denied rather than let through. §6
- A5 Shared grammar
- The rules format is shared across tools rather than a proprietary dialect. §8
| Harness | A1 Path rules | A2 Tree-resident | A3 Per-path | A4 Per-agent | A5 Shared grammar |
|---|---|---|---|---|---|
| Aider | yes, documented | partial, or documented gaps | yes, documented | no | partial, or documented gaps |
| Claude Code | yes, documented | partial, or documented gaps | yes, documented | no | no |
| Cline | yes, documented | partial, or documented gaps | yes, documented | no | partial, or documented gaps |
| Cursor | yes, documented | partial, or documented gaps | yes, documented | no | partial, or documented gaps |
| DeepSeek Harness | no | no | no | no | no |
| Gemini CLI | yes, documented | partial, or documented gaps | yes, documented | no | partial, or documented gaps |
| GitHub Copilot (agent surfaces) | yes, documented | no | yes, documented | no | no |
| goose | no | no | no | no | no |
| JetBrains AI Assistant / Junie | yes, documented | partial, or documented gaps | yes, documented | no | partial, or documented gaps |
| OpenAI Codex CLI | yes, documented | partial, or documented gaps | yes, documented | no | no |
| Pi | no | no | no | no | no |
| Windsurf / Devin | yes, documented | partial, or documented gaps | yes, documented | no | partial, or documented gaps |
| Zed | yes, documented | yes, documented | yes, documented | no | no |
B. Coverage — what do the rules actually gate?
- B1 Context gating
- Restricted content, and the names of restricted paths, are kept out of model context and not transmitted — reads, listings, indexing, attachments — not merely deprioritized. §3, §7
- B2 Shell coverage
- The restriction holds when the model reaches for the shell —
cat, subprocesses, terminal tools. §7 - B3 Write gating
- Rules cover create/modify/rename/delete, not only reads — a declarative do-not-touch. §7
- B4 Pre-flight
- Rules are evaluated before content is touched — at workspace open for ambient agents, before each operation otherwise — and a change takes effect no later than the next operation. §4
| Harness | B1 Context gating | B2 Shell coverage | B3 Write gating | B4 Pre-flight |
|---|---|---|---|---|
| Aider | partial, or documented gaps | no | no | partial, or documented gaps |
| Claude Code | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| Cline | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| Cursor | partial, or documented gaps | no | undocumented | undocumented |
| DeepSeek Harness | undocumented | partial, or documented gaps | partial, or documented gaps | yes, documented |
| Gemini CLI | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| GitHub Copilot (agent surfaces) | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| goose | undocumented | undocumented | undocumented | undocumented |
| JetBrains AI Assistant / Junie | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps | undocumented |
| OpenAI Codex CLI | partial, or documented gaps | yes, documented | yes, documented | undocumented |
| Pi | no | no | no | no |
| Windsurf / Devin | partial, or documented gaps | partial, or documented gaps | yes, documented | undocumented |
| Zed | partial, or documented gaps | no | yes, documented | undocumented |
C. Fail direction — which way do errors fail?
- C1 Deny precedence
- A restriction holds against tool-native grants: a session approval, allowlist entry, remembered permission or bypass mode does not lift it. §7
- C2 Fail-closed policy errors
- A malformed or invalid rule, or a policy file that cannot be read, restricts rather than being dropped. §5
- C3 Self-protection
- The agent cannot create, modify, or delete the policy that restricts it. §7
- C4 Policy as data
- The policy is evaluated in deterministic code and never enters model context as natural language — a policy the model can read is a prompt-injection surface. §9
| Harness | C1 Deny precedence | C2 Fail-closed errors | C3 Self-protection | C4 Policy as data |
|---|---|---|---|---|
| Aider | undocumented | undocumented | undocumented | undocumented |
| Claude Code | yes, documented | partial, or documented gaps | partial, or documented gaps | yes, documented |
| Cline | no | undocumented | partial, or documented gaps | undocumented |
| Cursor | undocumented | undocumented | partial, or documented gaps | undocumented |
| DeepSeek Harness | no | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| Gemini CLI | undocumented | no | no | undocumented |
| GitHub Copilot (agent surfaces) | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps | undocumented |
| goose | partial, or documented gaps | no | undocumented | no |
| JetBrains AI Assistant / Junie | no | undocumented | undocumented | undocumented |
| OpenAI Codex CLI | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| Pi | not applicable | not applicable | not applicable | not applicable |
| Windsurf / Devin | partial, or documented gaps | partial, or documented gaps | undocumented | undocumented |
| Zed | yes, documented | partial, or documented gaps | partial, or documented gaps | undocumented |
D. Enforcement quality — does the mechanism hold?
- D1 Harness enforcement
- Restrictions are enforced in deterministic harness code, never entrusted to the model's judgment or a system-prompt request. §9
- D2 Canonicalization
- Symlinks resolved and paths canonicalized before the policy check — a recurring class of enforcement bug. §5, §9, A.6
- D3 Deliberate override
- A restriction is lifted only by an explicit user action naming that restriction, for one invocation — never by a remembered setting, a blanket bypass mode, or consent the model parsed out of its own context. §7
- D4 Delegation
- Restrictions carry to subagents and spawned processes; they attenuate through delegation, never reset. §7
| Harness | D1 Harness enforcement | D2 Canonicalization | D3 Deliberate override | D4 Delegation |
|---|---|---|---|---|
| Aider | yes, documented | undocumented | undocumented | undocumented |
| Claude Code | yes, documented | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| Cline | partial, or documented gaps | partial, or documented gaps | no | undocumented |
| Cursor | partial, or documented gaps | partial, or documented gaps | undocumented | undocumented |
| DeepSeek Harness | partial, or documented gaps | partial, or documented gaps | no | partial, or documented gaps |
| Gemini CLI | partial, or documented gaps | partial, or documented gaps | no | undocumented |
| GitHub Copilot (agent surfaces) | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| goose | partial, or documented gaps | undocumented | no | undocumented |
| JetBrains AI Assistant / Junie | partial, or documented gaps | undocumented | no | undocumented |
| OpenAI Codex CLI | yes, documented | partial, or documented gaps | no | partial, or documented gaps |
| Pi | not applicable | not applicable | not applicable | no |
| Windsurf / Devin | yes, documented | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
| Zed | yes, documented | partial, or documented gaps | partial, or documented gaps | partial, or documented gaps |
What the matrix shows
Four columns carry the headline. A4 (per-agent) is ○ everywhere: no harness lets a directory say which tools are welcome; the closest, JetBrains' .aiignore, binds only Junie and lets the other agents in the same IDE through. A5 (shared grammar) has no ●: every rules format is a proprietary dialect, at best borrowing .gitignore syntax, and rules travel between tools only where one vendor chooses to read another's file. B1 (context gating) has no ●: no harness documents keeping the names of restricted files out of model context as well as their content. B2 (shell coverage) has a single ●: only OpenAI Codex CLI closes it, enforcing its deny rules in an OS sandbox that also covers spawned commands; seven harnesses close it only partly, mostly with something opt-in (a sandbox, a hook, approval prompts), and four not at all. The ? marks are a finding too: for Aider, Cursor and goose, seven of the seventeen questions have no documented answer, and nearly a fifth of all cells are ?.
Per-harness notes
One note per harness: what each score rests on, with the sources behind it.
Aider 0.86.2
.aiderignore, /read-only, --add-gitignore-files — long-standing, gitignore syntax (FAQ, options, commands) (A1/A3 ●, A5 ◐); the ignore file is aider's own and cannot name other tools (A4 ○), one per repository, "default: .aiderignore in git root" (A2 ◐). The FAQ describes it as a way to "ignore parts of the repo that aren’t relevant to your task"; enforcement is visible only in source. Matching is deterministic code — pathspec in repo.py (D1 ●) — and the tracked-file list that feeds the repo map ("a list of the files in the repo, along with the key symbols") drops ignored files (repo.py#L486); /add skips them "due to aiderignore or --subtree-only" (commands.py#L811-L812), but /read-only never consults it (B1 ◐). The edit path checks gitignore but not .aiderignore, and asks "Allow edits to file that has not been added to the chat?" instead (allowed_to_edit) (B3 ○); model-suggested shell commands run after a "Run shell command?" confirmation with no ignore check (base_coder.py#L2434-L2455) (B2 ○). The file is checked when a file is added and re-read when its mtime changes, at most once per second; files already in the chat are not re-checked (B4 ◐). Deny precedence, error handling, self-protection, policy-in-context, canonicalization, override and delegation are undocumented (?).
Claude Code 2.1.295
permissions.deny with Read()/Edit() path rules (permissions docs) (A1/A3 ●); rules are Claude Code's own JSON settings and bind no other tool (A4 ○, A5 ○); project settings can be committed with the repo (.claude/settings.json), but Claude Code reads that one file "from the session's primary working directory" (settings), with no per-directory files (A2 ◐). Vendor states enforcement is deterministic: "Permission rules are enforced by Claude Code, not by the model" (D1 ●), with documented precedence "deny, then ask, then allow". A Read deny also blocks Edit and Write on the same path, and Claude Code "refuses the call before any file access" (errors); NotebookEdit needs an Edit deny; rename and delete happen only through the shell, where deny rules reach "file commands Claude Code recognizes in Bash, such as cat, head, tail, sed, and tee" and redirection targets, with no statement for mv or rm (B3 ◐). Settings edits, permissions included, reach "the running session without a restart", but managed settings delivered by MDM or the claude.ai console "reach a running session on a schedule rather than on save" (B4 ◐). For context surfaces (Grep, Glob, @-mentions, IDE context) the vendor's own wording is a "best-effort attempt" (B1 ◐). Shell coverage is explicitly partial: rules "don't apply … to arbitrary subprocesses that read or write files indirectly"; the OS sandbox, which "is off by default", closes that, with an unsandboxed-retry escape hatch (allowUnsandboxedCommands, default true) approved by a prompt, by the auto-mode classifier, or by a matching allow rule, depending on mode (B2 ◐). Invalid managed sandbox values fail closed per the changelog (2.1.283), and an unparseable managed settings file stops every session; one the OS denies reading starts the session "without that file's policies" (2.1.285); in other settings files a malformed permission rule is skipped — Claude Code "skips those values and keeps the rest of the file in effect" (settings) (C2 ◐). Scoped rules "don't change which tools Claude sees. Claude Code checks them when Claude attempts a call, leaving the prefix intact", and a bare tool-name deny removes the tool rather than describing it (prompt caching) (C4 ●). CVE-2025-54794 was "prefix matching instead of canonical path comparison", fixed; deny rules now "apply when either the requested path or the file it resolves to matches", yet symlink bypasses of Read deny rules through @-mentions, IDE selections and @-mentioned folder listings were still being fixed in 2.1.289–2.1.290 (D2 ◐). Permission modes state that "Deny rules block in every mode, including bypassPermissions", and "PreToolUse hook decisions don't bypass permission rules" (C1 ●). Writes to protected paths, .claude among them, cannot be pre-approved by allow rules, yet in auto mode — "the built-in starting permission mode for interactive terminal and VS Code sessions" — they are "Routed to the classifier", and in bypassPermissions they are "Allowed" (C3 ◐). That is also the D3 gap: user deny rules lift only when the user edits them, but the built-in protection falls to a blanket mode, to a classifier model's judgment, and to a prompt option that allows .claude edits "for this session" (D3 ◐). Subagents: built-in ones inherit "the parent conversation's permission rules", a settings deny rule "applies to the main conversation and to subagents", and a subagent that declares bypassPermissions "keeps the main conversation's mode instead"; spawned shell processes carry the rules only inside the opt-in sandbox (D4 ◐).
Cline 4.1.23
.clineignore, gitignore syntax, one file "in your project root" — multi-root workspaces get one per workspace root, not per directory (A1/A3 ●, A2 ◐, A5 ◐); it cannot name other tools (A4 ○). Matching files are excluded from "the file listing Cline sees when starting a task", automatic context gathering and search results, but the docs state plainly that the file "is not a security or access-control boundary — ignored files can still be read via explicit @ mentions or shell commands" (B1 ◐). The page carries a deprecation banner and offers a PreToolUse hook script as the enforced replacement: opt-in, user-installed code that "actively blocks the tool call whenever a file read (read_files), edit (editor, apply_patch), or shell command (run_commands) targets a file matching a .clineignore pattern", parsing apply_patch add, update, delete and move headers (D1 ◐, B3 ◐). The hook "cancels the tool call before it runs — the file is never accessed", and the script reads .clineignore afresh on every call (B4 ◐). Its shell guard "is a conservative token check, not a full shell parser … a sufficiently creative command could still slip through" (B2 ◐); it "also blocks attempts to modify .clineignore itself so the agent cannot un-ignore files", though the hook file itself is not on its list (C3 ◐); "Paths are canonicalized lexically, but symlinks are not resolved" (D2 ◐); and "In the CLI, hooks are disabled in --yolo mode", so a blanket mode lifts the restriction (C1 ○, D3 ○). Subagents run with "Cline's built-in tools for the current mode", and "Approval settings don't apply inside a subagent"; whether hooks run for a subagent's tool calls is not stated (D4 ?). Error handling for a malformed or unreadable .clineignore and whether the policy reaches model context are undocumented (?).
Cursor 3.24.9
.cursorignore, gitignore syntax, one file "in your root directory", with an opt-in setting that searches parent directories, not subdirectories (ignore docs) (A1/A3 ●, A2 ◐, A5 ◐); the file binds all of Cursor's surfaces alike — "Agent, Tab, and Inline Edit" — with no way to name a tool (A4 ○). The docs disclaim completeness — "complete protection isn't guaranteed due to LLM unpredictability" — and state plainly that "the terminal and MCP server tools used by Agent cannot block access to code governed by .cursorignore" (B1 ◐, B2 ○); the IDE release notes record name leaks closed one surface at a time — "autocomplete in the prompt no longer suggests files excluded by .cursorignore", and directory listings now "honor .cursorignore patterns from parent folders when listing a subfolder" (B1 ◐). Whether the rules gate writes, and when rule changes take effect, is undocumented (B3/B4 ?). CVE-2025-64110: an agent could write a new .cursorignore that invalidated the existing ones; since 2.0, "the agents ability to create and edit cursorignore files has been blocked in all cases", and the terminal sandbox lists .cursorignore among paths "always write-protected, regardless of your sandbox.json configuration" (sandbox.json reference) — but that list does not name the .gitignore files Cursor also honors, and Run Everything mode runs with no sandbox (run modes) (C3 ◐). How malformed rules are handled is undocumented; for a file that fails to load, 3.22 has Cursor retry a failed startup .cursorignore scan "instead of leaving agent context reads stuck for the rest of the session" (3.22 notes), without saying what reads see meanwhile (C2 ?). CVE-2026-50548 and CVE-2026-50549 (Cato AI Labs) let the agent write files outside the workspace through a sandbox write-path override and a failed-canonicalization fallback through an in-workspace symlink; both fixed in Cursor 3.0 per the NVD records (D2 ◐). "Cursor blocks access to files listed in .cursorignore", under the same no-guarantee caveat (D1 ◐). Whether the rules hold against Run Modes grants, whether they reach model context, how they are overridden, and whether they carry to subagents is undocumented (C1/C4/D3/D4 ?).
DeepSeek Harness 0.2.1-alpha.1
No path rules: the file-effect policy is one of three sandbox modes (read-only, workspace-write, danger-full-access) over a workspace root, and "Normal tool calls derive workspaceRoot from the calling session's immutable cwd" (sandbox docs) (A1–A5 ○). One policy applies "to every confined bash, filesystem, and terminal call" (sandbox-policy README): subprocesses run under Seatbelt, bwrap/Landlock, or a Windows ACL runner whose "hard-link, unconfined-read, and AppContainer-ACL boundaries are current partial cases" (B2 ◐), and file-tool writes the mode fence refuses fail with FS_SANDBOX_DENIED (filesystem docs) — a mode, not a per-path do-not-touch (B3 ◐). "Tool layers call resolve for each execution", and the effective mode is the session's last sandbox/mode event, so a switch applies from the next call (B4 ●). An approved escalated retry "is a new call with a wider policy" (C1 ○), and danger-full-access, which "bypasses confinement", ships in the default preset table (permission presets), where "Session choices survive restart" (D3 ○). The same presets doc has misconfiguration fail at plugin load — configured entries named custom or auto throw — and "a missing projection key fails explicitly", and the sandbox seam rules that "Silent unconfined passthrough is never legal for a confined policy"; that covers mode and executor configuration, not path rules, which don't exist (C2 ◐). "Before each model request, the model receives the effective policy and workspace": enforced in sandbox code, but also stated to the model (C4 ◐). In-process subagents "retain the inherited sandbox override plus approval: never"; the statement is scoped to in-process backends, not the external ACP, Codex, and Claude Code providers (subagent docs) (D4 ◐). Enforcement fixes track the classic classes: POSIX symlink/parent-directory combinations, Windows drive-relative paths (v0.1.6-alpha.1, carried into v0.1.7-rc.1), Windows sandbox deletions escaping the authorized directory and across workspaces (v0.1.7-alpha.1); "Enforcing providers canonicalize the root where the files exist" (D2 ◐). CVE-2026-82533 (OX Research): the sandboxed agent could reach the harness's own unauthenticated control interface and elevate its session to unconfined execution — the enforcement layer operable by the thing it governs; fixed August 27, 2026 in 0.1.2-alpha.1, whose release notes require a one-time token for network access to the web interface, and the web-server docs now have the shipped Connection plugin supply "Host/Origin checks plus browser-session authentication for every Host API route and stream" (C3 ◐: the bar exists now, its guarantee is undocumented). SAFETY.md states plainly that sandboxing, approval prompts, and permission controls "do not guarantee isolation or prevent damage" (D1 ◐). Whether reads and listings are kept out of model context is undocumented (B1 ?).
Gemini CLI 0.63.0
.geminiignore (docs) plus .gitignore reuse (source) (A1/A3 ●, A5 ◐); .geminiignore is one file "in the root of your project directory" — nested .gitignore files are honored per directory (source), but that is the version-control file, not the harness's policy file (A2 ◐). The docs scope the file to "tools that support this feature" (B1 ◐). read_file enforces deterministically via shouldIgnoreFile(), but the listing and search tools let the model switch the check off: glob, list_directory and read_many_files take a model-set respect_gemini_ignore (tool definitions), and grep's no_ignore drops the .geminiignore filter (source) (B1/D1 ◐; D3 ○: the restriction lifts with no user action) — and a feature request on the project's tracker, closed as not planned, names cat via run_shell_command as the workaround for reading ignored files (#13775); only the opt-in tool sandbox, security.toolSandboxing with default: false (settings schema), turns ignored paths into kernel-denied paths for shell commands (source) (B2 ◐). "To apply the changes, you must restart your Gemini CLI session", per the same docs (B4 ◐). Negation handling has shipped a bug that errs restrictive (! rules fail to un-ignore, #5444, closed by the project's bot after a Stale label, with no linked fix), but the error paths fail open: the matcher library skips a pattern ending in an unescaped backslash without a warning (node-ignore), an unreadable .geminiignore loads as no rules — "continue without it" (source) — and the ignore check returns not-ignored on any exception (source) (C2 ○). The write tools carry no ignore check at all — write_file and replace never consult the ignore service, verifiable in source (write-file.ts, edit.ts); with the opt-in sandbox on, "individual tool executions (like shell_exec and write_file)" run inside it (sandbox docs), where ignored paths are masked (B3 ◐). Nothing protects .geminiignore itself: "If the workspace is writable, we allow editing .gitignore and .geminiignore by default" (sandbox source) (C3 ○). read_file checks the ignore rules against both the requested path and its resolved real path (source); other surfaces are undocumented (D2 ◐). Whether the rules hold against approval modes, whether ignore patterns reach model context, and whether they carry to subagents is undocumented (C1/C4/D4 ?).
GitHub Copilot (agent surfaces) Copilot CLI 1.0.93, VS Code 1.141.0
Content exclusion exists and is deterministic for completions, chat, and review. For the agent surfaces, GitHub's own pages disagree: the how-to still says "GitHub Copilot CLI and Agent mode in Copilot Chat in IDEs do not support content exclusion" (configuring exclusions), while the concepts page marks Copilot CLI as supported and states "Content exclusion is currently not supported in Edit and Agent modes of Copilot Chat in Visual Studio Code and other editors." The CLI changelog shows exclusion enforced there, shell commands included (v1.0.33, v1.0.64), and since v1.0.64 failing open: "Access is allowed until rules can be fetched" when the rules service is unreachable. Server-managed settings likewise "fail open" when no cached policy is available (v1.0.78), unless an administrator sets forceRemoteSettingsRefresh: then "An unsuccessful refresh leaves the policy unconfirmed, so affected operations are restricted" (enterprise managed settings), and an unrecognized disableBypassPermissionsMode value is enforced as "disable" "as a fail-closed default" (C2 ◐). The path rules that do reach an agent surface are Copilot CLI's own: Read(...), Edit(...), and Write(...) glob rules in enterprise managed settings, session --deny-tool patterns such as read(.env) and write(PATH) (configuration reference, command reference), and sandbox denied paths, which "take precedence over both kinds of grant" (local sandboxing) (A1/A3 ●). Agent mode in VS Code has narrower equivalents: deniedPaths in chat.agent.sandbox.fileSystem.userConfiguredPaths for terminal commands and their child processes, while "Built-in tools that don't start operating system processes use their own permission checks" (agent sandboxing), and chat.tools.edits.autoApprove globs that require approval for edits to sensitive files (sensitive files). None of them lives in the tree: for the repository settings file .github/copilot/settings.json, "Only the keys listed in the following table are supported at the repository level", permission rules not among them; sandbox policy is per project in app settings; content exclusion is server-delivered; repository hooks (.github/hooks/) can deny tool calls, but as code, not declarative path rules (A2 ○). Coverage is CLI-only: Read rules gate file reads, Edit/Write rules also cover a recognized set of shell redirections and in-place sed edits, but when the path "comes from a variable" "these path rules do not apply"; shell commands and built-in searches "run as sandboxed child processes, so the operating system enforces the policy directly" (B1/B2/B3 ◐). Managed settings re-apply hourly "without restarting the session", content exclusion "can take up to 30 minutes to take effect in IDEs", and "A running child process keeps the policy it received at launch" (B4 ◐). A write(PATH) match "resolves symlinks and . / .. segments", sandbox denied paths resolve "their written path and current target" though on Linux "a denied symbolic link protects its target, but does not reliably prevent the link itself from being replaced", and "content exclusions do not apply to symbolic links (symlinks) and repositories located on remote filesystems" (D2 ◐). The CLI's rules are enforced by the harness, but the restriction an organization declares through content exclusion is not enforced in IDE agent mode (D1 ◐). File-based managed settings are rejected when they are "symlinks, not owned by root, or world-writable"; the docs state no such guard for the user-level settings file (C3 ◐). v1.0.88 closed a management-layer fail-open where ACP, AHP-host, and --server sessions "previously ran with no managed MCP, permission, or plugin policy". Copilot CLI's own deny rules hold against grants: "Deny rules always take precedence over allow rules, even when --allow-all is set or a matching approval has been saved" (allowing tools). Sandbox denials do not: in VS Code "Approval to run outside the sandbox removes file system and network restrictions for that operation" (C1 ◐). A CLI sandbox bypass "applies to that attempt", but "A bypass prompt can also let you disable sandboxing for the rest of the current session" (sandbox settings), and in VS Code "If you approve a session-wide bypass, subsequent terminal commands in that session also run without those restrictions" (D3 ◐). For subagents, "Whether the policy applies, and how, depends on the tool a subagent invokes" (D4 ◐). Whether rule text ever reaches the model is undocumented (C4 ?).
goose 1.54.0
.gooseignore is gone from the current tree: the docs carry no page for it, the string survives in the repo's own .gitignore, and v1.44.0's "Remove stale gooseignore references" (#10203) was the cleanup. Tool permissions are per tool, not per path: "Each tool can be set to one of three permission levels" (Always Allow, Ask Before, Never Allow) (tool permissions) (A1–A5 ○). The only file-access policy a user can write is adversary mode's ~/.config/goose/adversary.md, "your policy, written in plain language" (for example "SSH keys, .env files, or credentials are read or transmitted"), judged by a reviewer that "uses the same model and provider goose is already configured with": model judgment over prose, not a rule (C4 ○). By default it reviews only shell calls, and "If the reviewer fails for any reason, the tool call is allowed through (fail-open)". v1.49.0 shipped "Give permission denies precedence" (#11477), giving "persisted hard-deny entries precedence over overlapping allow or prompt entries". But Auto mode approves every tool without consulting them (permission inspector: GooseMode::Auto => InspectionAction::Allow) (C1 ◐), and "Autonomous Mode is applied by default" (permission modes): a blanket mode that lifts every restriction (D3 ○). Subagents run only in that mode: "Subagents are disabled in manual approval, smart approval, and chat-only modes" (subagents). Hooks carry a documented deny contract (v1.44.0), though "By default a hook failure is logged and the tool call proceeds" unless set to on_failure: block (hooks docs) (D1 ◐). A malformed hook configuration "skips that plugin's hooks.json with a warning", and on_failure "does not make configuration-loading or matcher errors fail closed" (C2 ○). Read, shell and write gating, timing, self-protection, canonicalization, and delegation of restrictions are undocumented (B1–B4, C3, D2, D4 ?).
JetBrains AI Assistant / Junie AI Assistant 263.6800.10, Junie 262.2144.120
.aiignore uses "the same syntax as a .gitignore file" (A1/A3 ●), and AI Assistant also honors .cursorignore, .codeiumignore, or .aiexclude "as long as they are located in the root folder of the project" (A5 ◐); .noai "in the root directory of the project" is a whole-project kill switch (docs). Junie reads .aiignore "in the project root directory" (Junie docs), not per directory (A2 ◐). The file names no tool and binds only Junie: AI Assistant's agents page lists .aiignore as "Respected" for Junie and "Not respected" for Claude Agent, Codex, and GitHub Copilot, and "files listed in .aiignore can be processed by Claude Agent" (Claude Agent) (A4 ○). Enforcement is vendor-admitted best-effort: "ignored files may still be processed due to unforeseen issues" (docs), and "Only the contents of files listed in .aiignore are protected" (Junie docs); file names and paths stay visible (support KB) (B1/D1 ◐). Edits to ignored files are approval-gated rather than hard-blocked: Junie "will ask for explicit approval before viewing or editing" them (Junie docs) (B3 ◐). The Junie docs name two exceptions where Junie "might still have access to the files listed in .aiignore": "If Brave Mode is turned on", and "When executing a command that is added to the Action Allowlist". So a remembered allowlist entry and a bypass mode both lift the restriction: "if a command is allowlisted, Junie will not ask for confirmation, even if that command accesses files and folders listed in .aiignore" (support KB) (C1 ○). Other shell access stays approval-gated (B2 ◐), and Brave Mode lets Junie "execute all potentially sensitive actions without user approval" (D3 ○). These statements are from the IDE plugin; the Junie CLI docs do not mention .aiignore. Timing, fail direction, self-protection, policy-as-data, canonicalization, and delegation are undocumented (B4, C2, C3, C4, D2, D4 ?).
OpenAI Codex CLI 0.162.0
The long-standing read-restriction gap has begun closing: beta permission profiles ("Beta. Permission profiles are under active development and may change.") add per-path filesystem rules — a deny entry "Denies both reads and writes under the path", and glob deny entries are supported — configurable in project .codex/config.toml files: "Codex walks from the project root to your current working directory and loads every .codex/config.toml it finds", "the closest file to your working directory wins", and "Codex loads project-scoped config files only when the project is trusted" (advanced config). User-authorable per-path rules exist, in beta (A1/A3 ●); the files travel with the repo, but which ones apply depends on where the session starts, not on the path being accessed (A2 ◐). The .codexignore request #1397 was closed as a duplicate; its successor #2847 was closed as completed on 2026-06-29, a maintainer citing "a new feature in beta that implements this functionality". The format is a Codex-specific TOML profile (A5 ○), and a profile names no agent (A4 ○). A read grant means "Commands cannot create, modify, rename, or delete files there" (B3 ●). The profile semantics lean fail-closed: "When two entries target the same path, deny takes precedence over write, and write takes precedence over read", though "A more specific path can also reopen a narrower subtree inside a broader deny"; "Missing or empty filesystem tables keep filesystem access restricted and emit a startup warning", and "If the selected policy cannot be enforced by the platform sandbox, Codex refuses to run the command instead of silently running it unsandboxed" — but "If sandbox_mode appears in any loaded config file … Codex uses those older sandbox settings instead of default_permissions" (C2 ◐). Extending :workspace "keeps the workspace root's .codex directory read-only unless you explicitly override it" (C3 ◐). The deny list is enforced in sandbox code, but the harness also writes the denied paths and globs into model context as a developer message — "The active permission profile denies reading these paths/globs" (source) — so the names of denied paths reach the model (C4 ◐, B1 ◐). The enforcement substrate is an OS sandbox (macOS Seatbelt, Linux bubblewrap): "The sandbox applies to spawned commands, not just to built-in file operations", and commands like git or test runners "inherit the same sandbox boundaries" (sandboxing) (B2/B3 ●, D1 ●); rust-v0.162.0 fixed a crack in that substrate, where a user ripgrep config could leave "files matching deny globs unmasked" (#51527). "Subagents inherit your current sandbox policy" (subagents), but "Connectors, MCP servers, browser or computer-use surfaces, Codex cloud environment settings, and approved escalations use their own controls" (permissions) (D4 ◐). Whether an edited profile reaches a running session without a restart is undocumented; on Linux, WSL and Windows, deny-read globs are expanded when "Codex snapshots matches before sandbox startup" (B4 ?). On Linux, an approved command will "Preserve literal deny paths alongside resolved targets so Linux can reject denials that cross writable symlinks" (#48155) (D2 ◐). Approved commands "retain explicit filesystem denials" (rust-v0.159.0), and "Approved filesystem escalation can now grant broader write access while preserving denied reads" (rust-v0.161.0), yet :danger-full-access "removes local sandbox restrictions" (permissions) (C1 ◐). That blanket mode is the only lift short of editing the rule: there is no one-invocation override, and the model is told "Do not request escalation or additional permissions to read them" (D3 ○).
Pi 1.1.0
Ships no file-access rules: an issue on its tracker lists the only mechanisms as the coarse --tools flag, custom TypeScript hooks, and interactive confirmation (#4459, which proposed native allow/deny policy files and was auto-closed during a refactor: "Issues closed during this period will not be reviewed") (A1–B4 ○, C1–C4 and D1–D3 —). The security doc places safety outside the harness — "Safety comes from limiting the files, credentials, processes, and network services Pi can access and affect" — and spells out the consequence: the working folder "does not prevent commands from accessing other paths available to the Pi process", project trust "does not limit what tool calls can access or affect", and child processes "run with those same permissions" (D4 ○); it also counts "lack of a built-in sandbox" as expected behavior. What Pi does have is a deterministic enforcement point: the tool_call hook can block operations in host-side code before execution. The shipped permission-gate example blocks three pattern-matched bash commands (rm -rf, sudo, chmod/chown 777) when no UI is present, and a sibling protected-paths example blocks write/edit calls to a hard-coded list (.env, .git/, node_modules/). A policy layer could attach there, but these are opt-in examples: with no restriction shipped, there is nothing for the harness to enforce yet (D1 —).
Windsurf / Devin Devin Desktop 3.10.48, CLI 3000.11.3
.devinignore (with legacy .windsurfignore / .codeiumignore "still read and enforced alongside .devinignore"), gitignore syntax, one file at "the root of your repository": paths matched "are excluded from indexing and cannot be viewed, edited, or created by Devin" (docs) (A1/A3 ●, A2 ◐, A5 ◐, B3 ●); whether the names of ignored paths stay out of listings and context is not stated (B1 ◐). Since v3.9.19, "Cascade has been removed" and "Devin Local is now the only agent available in Devin Desktop" (changelog); Devin Local shares Devin CLI's permission rules, where "A deny rule always wins", and v3.7.16 has rules "from different levels (enterprise, mode, user, project, subagent) now compose predictably — an explicit deny: always wins". But the precedence table still ranks "Session-level grants (interactive approvals)" above project and user config, and only "Organization-level deny and ask rules cannot be overridden by project or user config" (C1 ◐). The same holds for Bypass mode, where "all tool calls are auto-approved without prompting": only organization rules are guaranteed against it (D3 ◐). Smart mode's model judgment "only applies where no rule already decides the call, so a deny rule blocks the action" (D1 ●); the .devinignore docs do not name where that file is enforced. An opt-in OS sandbox hides Read(...)-denied paths "from sandboxed commands entirely", "hidden for the whole session" (B2 ◐), and errs restrictive in places — non-Exec rules in sandbox.excluded are "ignored with a warning", and if sandbox resolution fails, the CLI "will refuse to start rather than running unsandboxed" — but not everywhere: on Linux, "unsupported glob rules are ignored and logged" (CLI v3000.4.16) (C2 ◐). The edit, write, apply_patch, and notebook_edit tools "now refuse to write through a symlink" (Desktop v3.6.27, CLI v3000.3.27), with reads unstated (D2 ◐), and background subagents "inherit any tool permissions you have already granted during the current session"; "Any tool that has not been pre-approved is automatically denied" (D4 ◐). Unstated: whether edits to rule files take effect mid-session (B4 ?), whether the agent is barred from editing .devinignore or .devin/config.json (C3 ?), and whether ignore patterns or rules enter model context (C4 ?).
Zed 1.23.2
private_files and read_only_files glob settings, project-resident (all settings); project settings files can also sit in subdirectories — "You can also add settings files in subdirectories for more granular control" (configuring Zed) — and the agent's file tools look the settings up for the path being accessed (source) (A1/A2/A3 ●). Tool permissions add path-matched always_deny rules for edit_file, write_file, delete_path, move_path and create_directory (B3 ●). Content of private files is gated, and list_directory and grep skip private entries, but find_path returns matching worktree entries without a private_files check (source), so names can still reach the model (B1 ◐). The terminal tool is governed by command-pattern rules, not path rules, and under the OS sandbox "Terminal commands can read most of the filesystem" (B2 ○). Fail direction is split: an invalid tool_permissions regex blocks the tool — "If any patterns failed to compile, block the tool call entirely" (source) — while v1.22.0 only stopped one invalid file pattern from discarding the valid exclusion/read-only/private rules beside it: the invalid entry itself is still dropped, only logged, and "If the combined set cannot be built, reports the error and matches nothing" (#64525, source) (C2 ◐). always_deny is "highest priority, cannot be overridden", and global auto-approve leaves "always_deny, always_confirm, built-in security rules, and paths inside Zed settings directories" still prompting or blocking (C1 ●). Agent edits inside .zed/, where project private_files live, always prompt (source), but sandboxed "Terminal commands can write inside open project directories, except for protected Git metadata" (C3 ◐). The sandbox's own restrictions lift through remembered grants, for "the rest of the current thread" or "always", up to allow_unsandboxed (D3 ◐). Subagents get "the same tools as the parent agent" (tools), so the file-tool checks carry, but processes spawned from the terminal are not bound by private_files, and the sandbox "does not sandbox … External Agents" (D4 ◐). Enforcement is deterministic editor code, confirmed by the project's own advisory for CVE-2026-27967: agent file tools checked private_files on logical paths, so symlinks escaped; patched in 0.225.9. Today, symlinks resolving outside the project trigger an always-prompt, while the private check still runs on the project-relative path (D1 ●, D2 ◐). Not documented: whether a settings edit reaches a running agent before its next operation (B4 ?), and whether private-file patterns or names enter model context (C4 ?). Rules name no agent (A4 ○) and use Zed's own settings format (A5 ○).
Method
Scored from primary sources wherever possible: vendor documentation, public source code, the project's own issue tracker, and security advisories. A ? means no authoritative statement was found either way — inference is not scoring. A ◐ with a fixed CVE means the mechanism exists and its failure mode is documented history, not that the current version is broken. OpenCode and OpenHands are not yet scored: a row here requires the full source pass. Re-scored as harnesses ship; dated changes land in the scoring history below.
Scoring history
October 8, 2026 (full re-score) — all thirteen harnesses re-scored against the current release of each, now recorded with each harness; source links pinned to those releases. Six requirements were reworded to match the agentaccess.txt specification more closely: A4 now also asks that a tool the rules do not name is denied; B1 covers the names of restricted paths and their transmission, not only their content; B3 adds renaming; B4 asks that a change takes effect no later than the next operation, not merely without a restart; C2 covers a policy file that cannot be read, not only a malformed rule; D3 asks that an override lasts one invocation and is never remembered.
Show 41 score changesHide score changes
- Aider: B2 undocumented changed to no, B3 undocumented changed to no, B4 undocumented changed to partial, or documented gaps, D1 undocumented changed to yes, documented
- Claude Code: B3 yes, documented changed to partial, or documented gaps, B4 yes, documented changed to partial, or documented gaps
- Cline: B1 no changed to partial, or documented gaps, B2 no changed to partial, or documented gaps, B3 undocumented changed to partial, or documented gaps, B4 undocumented changed to partial, or documented gaps, C1 undocumented changed to no, C3 undocumented changed to partial, or documented gaps, D2 undocumented changed to partial, or documented gaps, D3 undocumented changed to no
- Cursor: C2 partial, or documented gaps changed to undocumented, C3 undocumented changed to partial, or documented gaps
- DeepSeek Harness: B4 undocumented changed to yes, documented, C2 undocumented changed to partial, or documented gaps, C4 undocumented changed to partial, or documented gaps
- Gemini CLI: B1 yes, documented changed to partial, or documented gaps, D1 yes, documented changed to partial, or documented gaps, D3 undocumented changed to no
- GitHub Copilot (agent surfaces): C2 undocumented changed to partial, or documented gaps, D3 undocumented changed to partial, or documented gaps, D4 undocumented changed to partial, or documented gaps
- goose: C2 undocumented changed to no, C4 undocumented changed to no, D3 undocumented changed to no
- JetBrains AI Assistant / Junie: A4 partial, or documented gaps changed to no, B2 no changed to partial, or documented gaps, C1 undocumented changed to no
- OpenAI Codex CLI: A1 partial, or documented gaps changed to yes, documented, A3 partial, or documented gaps changed to yes, documented, D3 partial, or documented gaps changed to no, D4 yes, documented changed to partial, or documented gaps
- Pi: D1 partial, or documented gaps changed to not applicable
- Windsurf / Devin: B1 yes, documented changed to partial, or documented gaps, D3 undocumented changed to partial, or documented gaps
- Zed: B1 yes, documented changed to partial, or documented gaps, D3 undocumented changed to partial, or documented gaps, D4 undocumented changed to partial, or documented gaps
October 6, 2026 (initial scoring) — thirteen harnesses against seventeen requirements; every sourced cell checked against its live primary source.
Landscape shifts
Directional changes in agent harnesses, and in the operating systems they run on: not every feature, only the moves that change where file-access policy lives, who decides, or which way it fails.
- October 2, 2026 · Apple macOS · The OS will tighten its broadest file-access grant: Apple announced it will add controls so that granting Full Disk Access takes "very explicit user action", with no date given. Apple's stated reason is developers using it "in ways that could put users at risk", with AI agents named as a growing risk: "As AI agents become increasingly capable and autonomous, the risks associated with this level of access will grow substantially."
- September 29, 2026 · OpenAI Codex rust-v0.159.0 · Denials hold against approvals: "Approved commands retain explicit filesystem denials", and
.awsdirectories are protected by default under writable roots. - September 29, 2026 · Claude Code 2.1.285 · Denials hold against lower layers: project settings can no longer "reopen managed read-denies" in the sandbox.
- September 28, 2026 · Claude Code 2.1.284 · The default decision-maker moves from the user to a model: interactive and VS Code sessions now start in auto mode when no permission mode is configured, on every plan and provider.
- September 3, 2026 · goose v1.49.0 · Denials take precedence: "Give permission denies precedence".
Contributing
To add an issue, open a pull request to the harness.fail repository with a source, the affected harness, the date it was first disclosed, and one or two factual sentences on what failed. If it was fixed, name the version that fixed it.
Primary sources are preferred: an advisory, a CVE record, a vendor announcement, or the researcher's own write-up. Press coverage is fine when no first-hand account is public.
To dispute a matrix score, or to correct anything else on the page, open a pull request.
CONTRIBUTING.md has the row format and the fix statuses. If you would rather not edit JSON, open an issue there with the source instead.