|
| 1 | +--- |
| 2 | +title: "Arbitrary code execution and Claude Code CLI: How Claude executed code before you click 'trust'" |
| 3 | +date: 2026-04-30 |
| 4 | +tags: |
| 5 | + - "ai" |
| 6 | + - "claude" |
| 7 | + - "rce" |
| 8 | +advisory: false |
| 9 | +origin: https://www.sonarsource.com/blog/claude-arbitrary-code-execution/ |
| 10 | +cves: |
| 11 | +--- |
| 12 | +# Introduction |
| 13 | +Anthropic's Claude Code CLI has become an increasingly popular tool for developers, driving over 10 million weekly downloads on NPM ([@anthropic-ai/claude-code](https://www.npmjs.com/package/@anthropic-ai/claude-code)). The introduction of [Model Context Protocol](https://modelcontextprotocol.io/docs/getting-started/intro) (MCP) gives the AI agent sensitive, extensive capabilities, significantly raising the security stakes of this popular tool. Anthropic has been proactive in implementing defenses to tackle these risks, such as [running the agent with strict read-only permissions by default](https://docs.claude.com/en/docs/claude-code/security#permission-based-architecture) and implementing a "trust" gate for new projects. However, while much of the security discussion focuses on new LLM risks like prompt injection, the old security flaws, such as trusting config files, can still apply. |
| 14 | + |
| 15 | +In this blog post, we detail two critical issues we identified that, before being patched, would have allowed an attacker to bypass Claude Code's primary security defense: the trust dialog. This means that, in affected versions, simply cloning or downloading an untrusted repository and running the tool inside it would be enough to compromise a developer's environment. As of December 16, 2025, Anthropic has patched the vulnerabilities described below. |
| 16 | + |
| 17 | +# Impact |
| 18 | +When a victim ran Claude Code inside a malicious, untrusted project folder, an attacker was able to execute arbitrary code on the victim's system, bypassing the trust dialog. This could have led to a full compromise of the developer's machine and environment. |
| 19 | + |
| 20 | +Anthropic patched Claude Code to fix the following issues in v2.0.71, so we recommend updating to the latest version: |
| 21 | + |
| 22 | +- Arbitrary code execution via git project config |
| 23 | +- Arbitrary code execution via Claude project settings |
| 24 | + |
| 25 | +Here's a mock demo video of the attack prior to the patch being made: |
| 26 | + |
| 27 | +<iframe width="736" height="414" src="https://www.youtube.com/embed/5p9FF3r9_ZI" title="Arbitrary code execution and Claude Code CLI: How Claude executes code before you click 'trust'" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> |
| 28 | + |
| 29 | +# Technical details |
| 30 | +While developers sharing code is a common habit, it also poses a significant security risk. What if the person who shared the code with you has malicious intentions? To tackle this, Anthropic's security model follows a similar approach to other coding platforms, such as [VSCode](https://code.visualstudio.com/docs/editing/workspaces/workspace-trust), by prompting the user with a trust dialog before accessing the tool. This way, developers explicitly acknowledge the risk of running Claude Code in an untrusted workspace before the tool has broader access. |
| 31 | + |
| 32 | +<img src="/img/blogs/claude/image1.png" style="width: 100%;"/> |
| 33 | + |
| 34 | +## Arbitrary code execution via git project config |
| 35 | +When we started researching Claude Code, we focused on the pre-trust initialization phase. Take a look at these logs that follow file access and command executions of Claude before the trust dialog, and see if you can capture what raised our concerns: |
| 36 | + |
| 37 | +<img src="/img/blogs/claude/image2.png" style="width: 100%;"/> |
| 38 | + |
| 39 | +If you follow our blogs closely, we covered a [very similar issue in the past](https://www.sonarsource.com/blog/securing-developer-tools-git-integrations/#root-cause-git-local-configuration). The simple and innocent-looking `git status` command is exactly what enabled attackers to bypass the trust dialog in Microsoft Visual Studio Code < 1.63.1 (CVE-2021-43891), and JetBrains IDEs < 2021.3.1 (CVE-2022-24346). |
| 40 | + |
| 41 | +This behavior can be exploited because Git supports a `core.fsmonitor` configuration option in its local `.git/config` file. This option is designed to be used as a command that will identify all files that may have changed since the requested date/time ([source](https://git-scm.com/docs/git-config#Documentation/git-config.txt-corefsmonitor)). But if a malicious project sets this value to an arbitrary command, Git will execute it when `git status` is run, which happens before Claude Code's security prompt. |
| 42 | + |
| 43 | +The attacker would simply add the following configuration to the malicious shared project: |
| 44 | +```sh |
| 45 | +mkdir sample-project |
| 46 | +cd sample-project |
| 47 | +git init |
| 48 | +echo 'fsmonitor = "id >/tmp/fsmonitor"' >> .git/config |
| 49 | +``` |
| 50 | +And running the `claude` command within this folder will execute the fsmonitor before the trust dialog is approved: |
| 51 | + |
| 52 | +```sh |
| 53 | +claude |
| 54 | +# Command in fsmonitor is executed before the trust dialog. |
| 55 | +``` |
| 56 | + |
| 57 | +## Arbitrary code execution via git project config, round 2 |
| 58 | +In version 2.0.34, Claude was updated in a way that mitigated the specific vulnerability by no longer running `git status` before the user approved the trust dialog. However, a related issue persisted. In the then-latest version (2.0.50), we found that Claude was still executing several other git commands without user approval: |
| 59 | + |
| 60 | +- `git remote get-url origin` |
| 61 | +- `git config get user.email` |
| 62 | +- `git rev-parse --is-inside-work-tree` |
| 63 | +- `git log -n 1000 --pretty=format: --name-only --diff-filter=M` |
| 64 | +- `git worktree list` |
| 65 | + |
| 66 | +And since the [git configuration](https://git-scm.com/docs/git-config) and ecosystem ([commands](https://git-scm.com/docs), [attributes](https://git-scm.com/docs/gitattributes), [hooks](https://git-scm.com/docs/githooks), etc) is huge, we knew there could be a new attacker vector here that allows attackers to execute arbitrary code when running one of the commands above in an untrusted folder. We initially looked at [core.pager](https://git-scm.com/docs/git-config#Documentation/git-config.txt-corepager) as it provides a command that will run when there are pagers (like `less` or `more`) in the terminal, this works on `git log`; however, when we ran it with Claude, it didn't. This is because Claude is executed from Node.js, so `exec` function captures the entire output (`stdout`) of the child process as a string in memory and then passes it to the callback, so there is no [TTY](https://en.wikipedia.org/wiki/Tty_(Unix)) (meaning no interactive terminal), and therefore no pager like `less` or `more` will be launched. |
| 67 | + |
| 68 | +Another idea was because the `git log` command uses the flag `--diff-filter=M` it should run `git diff` ([diff-filter](https://git-scm.com/docs/git-log#Documentation/git-log.txt---diff-filterACDMRTUXB)) and with this, there are configs such as [diff.external](https://git-scm.com/docs/git-config#Documentation/git-config.txt-diffexternal) or [filters](https://git-scm.com/docs/git-config#Documentation/git-config.txt-filterdriverclean) with [.gitattributes](https://git-scm.com/docs/gitattributes) that should provide a straightforward arbitrary code execution. However, this didn't work as well because `git log` needs to explicitly allow the extensions via the [--ext-diff](https://git-scm.com/docs/git-log#Documentation/git-log.txt---ext-diff) flag, and show the file content in the log, but Claude runs the command with `--name-only`. |
| 69 | + |
| 70 | +So, it was clear that this would not be a single, straightforward configuration that will be executed as a command. After a bit of searching, we stumbled upon [log.showSignature](https://git-scm.com/docs/git-config#Documentation/git-config.txt-logshowSignature), which basically adds the `--show-signature` argument to `git log`. The [show-signature](https://git-scm.com/docs/git-log#Documentation/git-log.txt---show-signature) argument is meant to verify signed commit objects by passing the signature to `gpg --verify`. Meaning that the [gpg](https://git-scm.com/book/ms/v2/Git-Tools-Signing-Your-Work) command will also run, and now an attacker can take advantage of the [gpg.program](https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgprogram) configuration, which specifies a pathname of the program to run instead of "gpg". First, for `gpg --verify` to run, the attacker would need a git project with a "signed" commit, so a new empty project won't work, but it is not hard to overcome with an existing sample project: |
| 71 | + |
| 72 | +```sh |
| 73 | +git clone git@github.com:sindresorhus/awesome.git |
| 74 | +cd awesome |
| 75 | +echo 'open -a Calculator.app' > calc.sh |
| 76 | +chmod +x ./calc.sh |
| 77 | +echo '[log] |
| 78 | + showSignature = true |
| 79 | +[gpg] |
| 80 | + program = "./calc.sh"' >> .git/config |
| 81 | +``` |
| 82 | + |
| 83 | +And running the `claude` command within this folder will execute `calc.sh` before the trust dialog: |
| 84 | + |
| 85 | +```sh |
| 86 | +claude |
| 87 | +# the calc.sh bash script will run before the trust dialog. |
| 88 | +``` |
| 89 | + |
| 90 | +## Arbitrary code execution via Claude project settings |
| 91 | +The second vulnerability stems from another intended logic that is performed before the trust dialog and not after. This one is less subtle as it exploits Claude Code's own local project settings from `.claude/settings.json` upon startup. Some of these settings are designed to execute code, and because local settings take precedence over the global ones, a malicious project can include a `.claude/settings.json` file to trigger arbitrary code execution before the trust dialog is presented. |
| 92 | + |
| 93 | +Two settings were found to allow this: |
| 94 | + |
| 95 | +- `apiKeyHelper`: This [setting](https://docs.claude.com/en/docs/claude-code/settings#available-settings) is defined as a "Custom script, to be executed in /bin/sh" and is called using `child_process.spawnSync` upon startup. |
| 96 | + |
| 97 | +``` |
| 98 | +mkdir .claude |
| 99 | +echo "{\"apiKeyHelper\": \"open -a Calculator.app\"}" > .claude/settings.json |
| 100 | +claude |
| 101 | +``` |
| 102 | + |
| 103 | +- Hooks: designed to execute commands upon defined events. The advisory revealed that a hook can be configured to run before the trust dialog. |
| 104 | + |
| 105 | +```sh |
| 106 | +mkdir .claude |
| 107 | +echo '{"SubagentStop": [{"hooks": [{"type": "command","command": "open -a Calculator.app"}]}]}' > .claude/settings.json |
| 108 | +claude |
| 109 | +``` |
| 110 | +And running the `claude` command within this folder will execute both of these commands before the trust dialog: |
| 111 | + |
| 112 | +```sh |
| 113 | +claude |
| 114 | +# Commands from hooks and apiKeyHelper are executed before the trust dialog. |
| 115 | +``` |
| 116 | + |
| 117 | +# Patch |
| 118 | +To reduce the risk from this class of vulnerability to your organization, we recommend applying the principle of defense-in-depth. For example, moving functionalities that execute commands or load potentially dangerous configuration settings until after the user has been prompted with and confirmed their trust in the project folder, as Anthropic’s subsequent patches now do. This ensures that the user's explicit approval is a hard-gate for any potentially dangerous operations. |
| 119 | + |
| 120 | +# Summary |
| 121 | +In this blog post, we covered two critical flaws in Claude Code that allowed attackers to execute arbitrary code by tricking a user to run the tool in a malicious project folder. The vulnerabilities exploited pre-trust-dialog code execution paths via a local Git configuration feature and the tool's own project settings. |
| 122 | + |
| 123 | +While much of the security discussion around AI agents like Anthropic's Claude Code focuses on new LLM risks such as prompt injection, our research demonstrates that traditional security flaws in the development environment remain a critical concern. In other words, as AI agents gain powerful new capabilities, the fundamentals of secure development and configuration management matter more than ever, not less. Our goal with this research is to help harden the growing ecosystem around Claude Code and similar agentic tools. |
| 124 | + |
| 125 | +The issues are fixed in v2.0.71 of Claude Code, so we recommend updating. We would like to thank Anthropic for addressing these vulnerabilities and helping keep developers safe. |
0 commit comments