claude-code - 💡(How to fix) Fix [BUG] Windows clipboard write exposes content in PowerShell argv (captured by EDR/SIEM ProcessCommandLine telemetry) [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#53395Fetched 2026-04-26 05:16:56
View on GitHub
Comments
1
Participants
1
Timeline
7
Reactions
0
Author
Participants
Timeline (top)
labeled ×5commented ×1renamed ×1

Error Message

Error Messages/Logs

Code Example

powershell.exe -NoProfile -Command "Set-Clipboard -Value ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('<BASE64_OF_RESPONSE_CONTENT>')))"

---

powershell.exe -NoProfile -Command "[Console]::In | Set-Clipboard"

---

# Reproduction query (MDE Advanced Hunting):

DeviceProcessEvents
| where Timestamp > ago(1h)
| where InitiatingProcessFileName =~ "claude.exe"
     or InitiatingProcessParentFileName =~ "claude.exe"
| where ProcessCommandLine has "Set-Clipboard"
     and ProcessCommandLine has "FromBase64String"
| project Timestamp, ProcessCommandLine

# Each row contains the entire selected/copied content, base64-encoded.
# Decoded with [Convert]::FromBase64String($base64) in PowerShell,
# or with base64_decode_tostring() in KQL.

# Observed pattern (sanitized — actual base64 redacted):

powershell.exe -NoProfile -Command "Set-Clipboard -Value ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('<BASE64_OF_RESPONSE_CONTENT>')))"

---

{
     "env": {
       "CLAUDE_CODE_NO_FLICKER": "1"
     }
   }

---

DeviceProcessEvents
   | where Timestamp > ago(1h)
   | where InitiatingProcessFileName =~ "claude.exe"
        or InitiatingProcessParentFileName =~ "claude.exe"
   | where ProcessCommandLine has "Set-Clipboard"
        and ProcessCommandLine has "FromBase64String"
   | project Timestamp, ProcessCommandLine
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

On Windows, Claude Code's clipboard write mechanism passes the copied content as a base64-encoded literal in the command-line arguments of a spawned PowerShell subprocess. This affects BOTH the /copy slash command AND ordinary terminal text selection in the Claude Code TUI — both code paths produce the same leak pattern in ProcessCommandLine. The result is leakage of all copied/selected content into EDR / SIEM telemetry pipelines (Microsoft Defender for Endpoint, CrowdStrike Falcon, SentinelOne, Sysmon EID 1) with default 30-day retention.

The base64 layer is trivially reversed and is itself a known suspicious pattern that EDRs explicitly hunt for — so this both leaks user data AND looks suspicious to security tooling.

Observed pattern in DeviceProcessEvents.ProcessCommandLine:

powershell.exe -NoProfile -Command "Set-Clipboard -Value ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('<BASE64_OF_RESPONSE_CONTENT>')))"

Empirically confirmed against my own MDE Advanced Hunting telemetry: entire copied responses, KQL queries, admin commands — all decodable from the base64 in ProcessCommandLine. First validated via /copy (the obvious case), then realized the same pattern was also being produced by plain terminal selections I had not explicitly copied — so the leak is present on BOTH user-initiated paths.

What Should Happen?

Clipboard writes should NOT expose the copied user content in process command-line arguments captured by EDR telemetry. The content should be passed via a channel that is not captured in ProcessCommandLine. Three options, in order of preference:

  1. Pipe via stdin (preferred — what clipboardy, the standard Node.js clipboard library, already does on Windows):

    powershell.exe -NoProfile -Command "[Console]::In | Set-Clipboard"

    Then write the content to the spawned process's stdin. Content never appears in argv.

  2. Use a Node.js native Windows clipboard binding (NAPI module calling OpenClipboard / SetClipboardData directly). Zero subprocess.

  3. Use -EncodedCommand for a small wrapper script that reads stdin (the script itself ends up in argv, but not the user content).

Same fix logic applies on macOS (pbcopy via stdin, not argv) and Linux (xclip -selection clipboard via stdin) — see Additional Information for the cross-platform concern.

Error Messages/Logs

# Reproduction query (MDE Advanced Hunting):

DeviceProcessEvents
| where Timestamp > ago(1h)
| where InitiatingProcessFileName =~ "claude.exe"
     or InitiatingProcessParentFileName =~ "claude.exe"
| where ProcessCommandLine has "Set-Clipboard"
     and ProcessCommandLine has "FromBase64String"
| project Timestamp, ProcessCommandLine

# Each row contains the entire selected/copied content, base64-encoded.
# Decoded with [Convert]::FromBase64String($base64) in PowerShell,
# or with base64_decode_tostring() in KQL.

# Observed pattern (sanitized — actual base64 redacted):

powershell.exe -NoProfile -Command "Set-Clipboard -Value ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('<BASE64_OF_RESPONSE_CONTENT>')))"

Steps to Reproduce

  1. SETUP CAVEAT — tested ONLY with the CLAUDE_CODE_NO_FLICKER=1 opt-in flag enabled. Per the Claude Code changelog, this env var opts into "flicker-free alt-screen rendering with virtualized scrollback" — a DIFFERENT rendering path from the default. The reporter's ~/.claude/settings.json contains:

    {
      "env": {
        "CLAUDE_CODE_NO_FLICKER": "1"
      }
    }

    Whether the same leak occurs with the default rendering path (flag absent or unset) has NOT been verified. Maintainers should A/B test both paths to confirm scope.

  2. On Windows, install Claude Code (any recent version, confirmed on v2.1.119).

  3. Have an EDR running that captures ProcessCommandLine — Microsoft Defender for Endpoint is enabled by default on Windows 11 (even free Defender records this in local ETW; MDE Plan 1/Plan 2 surface it in the cloud DeviceProcessEvents table).

  4. Launch Claude Code in any terminal (Windows Terminal, Git Bash, etc.).

  5. Trigger a clipboard write via EITHER of the two known paths:

    • Path A — /copy slash command: type /copy in the Claude Code TUI.
    • Path B — terminal text selection: select any text in the Claude Code TUI with the mouse (no further keypress needed; the selection itself triggers the same code path).

    Both paths produce the same Set-Clipboard PowerShell subprocess pattern in EDR telemetry.

  6. Wait a few seconds for telemetry ingestion, then query the EDR. With MDE Advanced Hunting:

    DeviceProcessEvents
    | where Timestamp > ago(1h)
    | where InitiatingProcessFileName =~ "claude.exe"
         or InitiatingProcessParentFileName =~ "claude.exe"
    | where ProcessCommandLine has "Set-Clipboard"
         and ProcessCommandLine has "FromBase64String"
    | project Timestamp, ProcessCommandLine
  7. Each row contains the entire selected/copied content, base64-encoded inside a Set-Clipboard -Value ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('...'))) literal.

  8. Decode any row's base64 with [Convert]::FromBase64String($base64) in PowerShell or base64_decode_tostring() in KQL — the original copied text is recovered verbatim.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.1.119

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

Impact

  • On configurations where the host EDR or SIEM captures ProcessCommandLine (e.g., Microsoft Defender for Endpoint Plan 1/2 by default, CrowdStrike Falcon, SentinelOne, or Sysmon EID 1 forwarded to a SIEM such as Splunk / Microsoft Sentinel), every clipboard write in the Claude Code TUI on Windows — whether via /copy or via plain mouse text selection — exposes the copied content in the captured telemetry. On MDE specifically, default Advanced Hunting retention is 30 days; the base64-encoded literal is trivially decodable.
  • Cloud-hosted EDR telemetry has historical compromise precedents (e.g., Storm-0558, 2023). Any future compromise of the EDR backend would expose every Claude Code interaction copied via this mechanism.
  • The base64 layer provides zero privacy benefit. It only adds suspicious-looking telemetry: EDRs specifically watch for FromBase64String in PowerShell command lines as an obfuscation indicator (well-known threat hunting pattern in Splunk / Sentinel / MDE built-in detections). So this both leaks user data AND triggers heuristic alerts on legitimate Claude Code usage.

Cross-platform concern

Based on near-miss issue #41954, a similar pattern exists on macOS (pbcopy) and Linux (xclip). If those tools receive the content via argv (rather than stdin), they leak the same way to macOS EDR (CrowdStrike, Jamf telemetry) and Linux auditd / EDR (Wazuh, Falco, etc.). Recommend auditing all three platforms — the clipboardy reference implementation already handles this correctly cross-platform via stdin streams, so it can serve as a template for the fix.

Related (verified not duplicates)

  • #41954 — TUI selection spams clipboard on every render (macOS/Linux pbcopy/xclip). Behavioral overlap, but does not mention Windows / EDR / argv-vs-stdin / privacy implications. Could be merged or cross-linked.
  • #42417 — OSC 52 mojibake (Windows encoding bug, unrelated to this).
  • #18653 — Tool result content sanitization hook (different scope).
  • #44868, #44909 — Read/grep secret leaks into model context (different vector — input to model, not output to host clipboard).

Environment (additional context)

  • Claude Code: v2.1.119
  • OS: Windows 11 Enterprise 25H2
  • EDR: Microsoft Defender for Endpoint Plan 2
  • Setup caveat: tested only with CLAUDE_CODE_NO_FLICKER=1 env flag set globally in ~/.claude/settings.json (opts into alt-screen rendering with virtualized scrollback per official changelog). Behavior with default rendering path (flag absent / unset) NOT verified — maintainers should A/B test both paths.
  • Confirmed via empirical Advanced Hunting query (above) — entire copied content was decodable from ProcessCommandLine in my tenant telemetry.

Issue investigated and drafted with Opus 4.7 (Anthropic).

extent analysis

TL;DR

To fix the clipboard content leakage issue in Claude Code on Windows, modify the clipboard write mechanism to pass the content via stdin instead of as a base64-encoded literal in the command-line arguments of the spawned PowerShell subprocess.

Guidance

  • Identify the current implementation of the clipboard write mechanism in Claude Code and modify it to use stdin for passing the content, similar to the clipboardy library.
  • Verify that the modified implementation does not expose the copied content in the ProcessCommandLine captured by EDR telemetry.
  • Test the fix on both the /copy slash command and terminal text selection paths to ensure that the leakage is resolved for both cases.
  • Consider auditing the implementation on macOS and Linux platforms to ensure that the content is not leaked via argv.

Example

The modified PowerShell command could be similar to the following:

powershell.exe -NoProfile -Command "[Console]::In | Set-Clipboard"

Then, write the content to the spawned process's stdin.

Notes

The fix should be applied to all three platforms (Windows, macOS, and Linux) to ensure that the content is not leaked via argv. The clipboardy library can serve as a reference implementation for the fix.

Recommendation

Apply the workaround by modifying the clipboard write mechanism to use stdin for passing the content, as this approach is preferred and already implemented in the clipboardy library.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING