Skip to content

hook subprocess spawn fails on corp Windows: bash.exe path emitted with '..' traversal, rejected by DLP/EPM #61

Description

@chirag127

Problem

On a corporate-managed Windows 11 laptop (SAP CPIT DLP + EPM active), every Claude Code hook (post-tool-use, session-start, stop, etc.) fails silently with:

Skipping command-line '"C:\Program Files\Git\bin\..\usr\bin\bash.exe"'
('C:\Program Files\Git\bin\..\usr\bin\bash.exe' not found)
Need a valid command-line; Edit the string resources accordingly

The .. traversal in the path (Git\bin\..\usr\bin\bash.exe) trips the endpoint agent's subprocess-guard — that's a classic path-injection shape, so the guard refuses to CreateProcess even though the file resolves fine.

Environment

  • Windows 11 Enterprise (build 26200), SAP CPIT DLP/EPM active
  • Node v22.x, cavemem installed via npm i -g at AppData/Roaming/npm/node_modules/cavemem
  • Both C:\Program Files\Git\bin AND C:\Program Files\Git\usr\bin on user PATH
  • where.exe shC:\Program Files\Git\usr\bin\sh.exe (resolves clean)
  • where.exe bashC:\Program Files\Git\usr\bin\bash.exe

Verified

  • ls "C:\Program Files\Git\bin\..\usr\bin\bash.exe" from Git Bash → resolves (46K + 2.3M binaries at both paths)
  • Same hook invoked from a non-managed shell works fine
  • Hook is non-blocking so nothing breaks — cavemem just misses the observation for every affected turn

Suggested fix

Canonicalize the bash.exe path before handing it to CreateProcess:

// somewhere in hook-spawn code
const bashPath = require('path').resolve(rawBashPath);  // strips ..
// or
require('fs').realpathSync(rawBashPath);

Corp EPM agents accept the canonical form (C:\Program Files\Git\usr\bin\bash.exe) — I verified by hand.

Why this matters

Corp-managed devs are a real slice of cavemem's audience; the "Executable not found in $PATH: sh" fix already documented in the wiki covers user-PATH gaps but not this traversal-guard variant.

Happy to test a patched build against the CPIT-guarded machine if useful.

Thanks for the great work on cavemem — cross-agent persistent memory is one of the pieces I actually reach for daily.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions