Skip to content

Bash tool silently collapses \\ to \ in command text, corrupting regex and paths #88561

Description

@bwillkom

Summary

The Bash tool collapses the two-character sequence \\ into a single \ in the
command string before the shell parses it. This happens inside single quotes,
inside double quotes, and inside a quoted heredoc (<<'EOF') alike, so the POSIX
guarantee that single quotes preserve backslashes literally does not hold.

It is not a general escape-decode — \n passes through untouched. It is specifically
the two-backslash sequence.

The failure is silent: a mangled backslash escape usually remains valid regex,
so sed/grep/awk match something different, exit 0, and report success.

Environment

Claude Code 2.1.224
OS Windows 11 Pro 10.0.26200
Shell Git Bash — GNU bash 5.3.9(1)-release (x86_64-pc-cygwin), MINGW64_NT-10.0-26200
Tools affected Bash tool only. The PowerShell tool is not affected.

Only tested on Windows/Git Bash. Whether macOS and Linux shells are affected is
untested and worth checking.

Minimal reproduction

printf '%s\n' 'a\\b'

Expected: a\\b (single quotes are literal in POSIX sh)
Actual: a\b

Observed mapping, across every quoting form including quoted heredocs:

Typed in a Bash command What the shell receives
\ \
\\ \ ← one is eaten
\\\\ \\

Proof that it is the tool layer, not bash or MSYS2

Same bytes, same bash, same quoting — only the transport differs.

Write a script file containing exactly (verified on disk with od -c):

printf 'from a SCRIPT FILE: [%s]\n' 'a\\b'

Then compare:

$ bash /path/to/repro.sh
from a SCRIPT FILE: [a\\b]        <-- correct

$ (same line typed into the Bash tool)
TYPED INTO TOOL:    [a\b]         <-- one backslash eaten

Because bash reading the identical text from disk behaves correctly, this isolates
the defect to the Bash tool's command transport. It is not bash, and not MSYS2/Cygwin
argv path conversion (which would not affect heredoc content anyway — heredoc bodies
are script text, not argv, and they are collapsed too).

Why this is worse than a normal escaping bug

It corrupts data while reporting success. Given a file containing a\b:

sed 's/a\\b/[HIT]/' file

The author intends a literal backslash. sed instead receives a\b, where \b is
GNU sed's word-boundary metacharacter — a perfectly valid pattern. sed matches
just the a, substitutes, exits 0, and writes the file.

Verified byte-for-byte, the result is [HIT]\b, not [HIT].

Nothing errors at any layer. In our case this presented as sed -i and perl -i
calls that exited 0 with the file's md5 unchanged — which reads exactly like a
blocked or sandboxed write, sending us down a permissions/filesystem dead end. The
writes were fine; the patterns simply never matched.

awk is the only tool that hints at it, warning:

awk: warning: escape sequence `\S' treated as plain `S'

Impact

Any Bash-tool command that needs a literal backslash is affected, most commonly:

  • sed/grep/awk/perl patterns matching literal backslashes
  • Windows path manipulation where paths are escaped as \\
  • regex escapes generally, where the eaten backslash silently changes the pattern's
    meaning rather than producing an error

Agents that store shell commands in instruction/config files and later type them into
the Bash tool inherit the bug at execution time, even though the stored text is correct.

Workarounds

  1. Double every literal backslash: type \\\\ to get \\.
  2. Use the Edit/Write tools or the PowerShell tool for anything involving backslashes.
  3. Put the command in a script file and execute that — script files are immune.
  4. Build the backslash from octal inside the shell, e.g. PAT=$(printf '\134\134'),
    which sidesteps the transport entirely.

Suggested fix

Stop unescaping \\ in the command string, or document the transport's escaping
contract explicitly. Failing that, surfacing a warning when a command contains \\
would at least make the corruption visible rather than silent.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:bashbugSomething isn't workinghas reproHas detailed reproduction stepsplatform:windowsIssue specifically occurs on Windows

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions