Repository navigation
On Windows, scan -g finds no Composer global packages in the default %APPDATA%\Composer home, so apply -g and vex -g silently do nothing #438
Description
[agent] Found by the scheduled Composer bug-hunt routine (ledger #321).
Summary
On Windows, with COMPOSER_HOME unset (the normal setup), socket-patch scan -g discovers zero Composer packages even though composer global require installed them under Composer's default global home, %APPDATA%\Composer\vendor. scan -g --mode agent prints No global packages found. and exits 0, and vex -g has nothing to attest. If you set COMPOSER_HOME to the same directory explicitly, everything works.
Root cause (two compounding gaps in get_composer_home):
crates/socket-patch-core/src/crawlers/composer_crawler.rs:374runscomposer global config homethroughSystemCommandRunner::run(crates/socket-patch-core/src/utils/process.rs:137). That callsCommand::new("composer")directly, without the PATHEXT-awareresolve_toolthat the same file provides. On Windows, Composer is installed ascomposer.bat(setup-php:C:\tools\php\composer+composer.bat; the official installer works the same way), so the spawn fails and returnsNone..github/workflows/composer-compatibility.yml:18-20already notes that "Command::new("composer")cannot resolvecomposer.bat".- The platform fallback (
composer_crawler.rs:396-410) probes only$HOME/.composerand$HOME/.config/composer. It never probes Composer's Windows default,%APPDATA%\Composer. On Linux it also ignores$XDG_CONFIG_HOME/composer, which Composer uses whenXDG_CONFIG_HOMEis set. So the fallback can't recover. Confirmed locally on Linux: withXDG_CONFIG_HOME=/x/xdgand composer run asphp composer.phar(not on PATH),scan -greportsNo global packages found.
Impact
Global Composer tools on Windows (phpstan, php-cs-fixer, laravel/installer, and so on) can't be scanned, patched or attested with -g. The failure is silent: exit 0 and "No global packages found." This violates the maintainer requirement that scan -g must find every globally installed package with a patch.
Repro (Git Bash on Windows, any Composer 1.10–2.10)
unset COMPOSER_HOME
composer global require <vendor>/<pkg-with-a-patch> # lands in %APPDATA%\Composer\vendor
socket-patch scan -g --json --ecosystems composer # packagesWithPatches: 0, scannedPackages: 0
socket-patch scan -g --mode agent --yes --ecosystems composer # "No global packages found." exit 0
COMPOSER_HOME="$APPDATA/Composer" socket-patch scan -g --json --ecosystems composer # found: 1The probe used a local path-repo package acme/tool@1.0.0 and a mock patch API (no secrets).
Expected vs actual
- Expected: CLI_CONTRACT.md
--global/-g: "Operate on globally-installed packages". The crawler doc comment says global mode checks "$COMPOSER_HOME/vendor/(env var, command fallback, or platform defaults)", and%APPDATA%\Composeris Composer's platform default on Windows. - Actual: the command fallback can't spawn
composer.bat, and the platform defaults omit%APPDATA%\Composer, so nothing is found.
OS × version
| OS | Composer | scan -g (default home) |
apply -g / vex -g |
same home with explicit COMPOSER_HOME |
|---|---|---|---|---|
| windows-latest | 1.10.28 (PHP 8.1) | fail (0 found) | fail | pass |
| windows-latest | 2.2.30 (PHP 8.4) | fail (0 found) | fail | pass |
| windows-latest | 2.10.3 (PHP 8.4) | fail (0 found) | fail | pass |
| macos-latest | 1.10.28 / 2.2.30 / 2.10.3 | pass (~/.composer) |
pass | pass |
| ubuntu-latest + local Linux | 1.10.28 / 2.2.30 / 2.8.12 / 2.10.3 | pass | pass | pass |
Linux, composer not on PATH, XDG_CONFIG_HOME set |
2.2.30 | fail (0 found) | n/a | n/a |
Windows reproduced in two separate probe runs (6 jobs): https://github.com/SocketDev/socket-patch/actions/runs/36823671080 and https://github.com/SocketDev/socket-patch/actions/runs/36827949605
First bad version
Not a regression from v5. The global branch (composer_crawler.rs:52-64) predates the shallow history, and the same code ships in v4.0.0.
Suspect code
crates/socket-patch-core/src/utils/process.rs:137(Command::new(bin), noresolve_tool)crates/socket-patch-core/src/crawlers/composer_crawler.rs:374and:396-410(fallback candidates)
crates/socket-patch-core/src/crawlers/ruby_crawler.rs:549 (gem env) goes through the same runner. That's out of scope here, and I've handed it to the bundler routine as a lead.
Activity
composer: run 3 (global mode; #438, #439)
mikolalysenko commentedon Oct 1, 2026
[agent] Shares root cause with #421, #434, #440: the global package-manager probes go through
SystemCommandRunner::run, which spawns the bare tool name withCommand::new(bin)(no PATHEXT, sogem.cmd/npm.cmd/yarn.cmd/composer.batare never found on Windows) and inherits the project cwd. Will be fixed together; the missing%APPDATA%\Composer/$XDG_CONFIG_HOME/composerfallbacks inget_composer_homeride along in the same PR. Triage: priority:p2 (Composer).[agent] Claiming this issue (with #421, #434, #440; shared root cause: global PM probes spawn the bare tool name from the project cwd via SystemCommandRunner). Branch: agent/fix-global-probe-tool-spawn. Claim-ID: 2026-10-01T07:21:08Z-824845
Generated by Claude Code
mikolalysenko commentedon Oct 1, 2026
[agent] Fix in progress: #442
Generated by Claude Code
Find global package managers on Windows
Fix global PM probes spawning bare names from the project (#421, #434, …