GeezerVison is showing github.com — Composer crawler ignores a vendor-dir set in the global Composer config, so scan -g and agent scans report "No packages found" and leave installs unpatched · Issue #439 · SocketDev/socket-patch
Composer crawler ignores a vendor-dir set in the global Composer config, so scan -g and agent scans report "No packages found" and leave installs unpatched #439Description[agent] Found by the scheduled Composer bug-hunt routine (ledger #321).
Summary
Composer resolves vendor-dir through its config cascade: COMPOSER_VENDOR_DIR, then the project's composer.json config.vendor-dir, then the user-level $COMPOSER_HOME/config.json. The socket-patch Composer crawler follows only part of that cascade, so real installs go undiscovered:
- Global (
-g): get_vendor_paths hardcodes $COMPOSER_HOME/vendor (crates/socket-patch-core/src/crawlers/composer_crawler.rs:52-64). If the global project sets config.vendor-dir (composer global config vendor-dir deps, or "config":{"vendor-dir":"deps"} in $COMPOSER_HOME/composer.json), or COMPOSER_VENDOR_DIR is exported, composer global require installs to $COMPOSER_HOME/deps. scan -g then finds 0 packages, and scan -g --mode agent prints No global packages found. with exit 0.
- Local (agent mode):
resolve_local_vendor_dir (composer_crawler.rs:473-492) reads COMPOSER_VENDOR_DIR and the project composer.json, but not the user-level $COMPOSER_HOME/config.json. After composer config -g vendor-dir lib, every project's composer install writes to lib/, and socket-patch scan --mode agent reports No composer packages found. (exit 0) while the package stays unpatched.
In both cases the failure is silent, with exit 0 and nothing patched or attested.
Repro (Linux; Composer 2.8.12, mock patch API, local path-repo package acme/[email protected])
# 1. global
export COMPOSER_HOME=$PWD/ch
composer global config repositories.local '{"type":"path","url":"/abs/pkgs/tool","options":{"symlink":false}}'
composer global config vendor-dir deps
composer global require acme/tool:1.0.0 # -> $COMPOSER_HOME/deps/acme/tool
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
socket-patch scan --global-prefix "$COMPOSER_HOME/deps" --json --ecosystems composer # finds 1 (workaround)
# 2. local, user-level config
composer config -g vendor-dir lib # writes $COMPOSER_HOME/config.json
composer install # -> ./lib/acme/tool
socket-patch scan --mode agent --yes --ecosystems composer # "No composer packages found."
COMPOSER_VENDOR_DIR=gdeps composer global require … followed by COMPOSER_VENDOR_DIR=gdeps socket-patch scan -g also finds nothing. Composer resolves the variable against the global home, while the global branch never reads it.
Expected vs actual
- Expected: CLI_CONTRACT.md
--global: "Operate on globally-installed packages". The crawler's local-mode doc promises COMPOSER_VENDOR_DIR / config.vendor-dir support, and Composer applies the same cascade (including config.json) to the global project and to every local one. The maintainer requirement for -g is that none may be missing.
- Actual: packages installed under a configured vendor-dir are invisible, and the commands exit 0.
OS × version
| OS |
Composer |
global vendor-dir → scan -g / apply -g |
user config.json vendor-dir → local agent scan |
| Linux (local) |
1.10.28, 2.2.30, 2.8.12, 2.10.3 (PHP 8.3) |
fail (each run twice) |
fail (2.8.12, twice) |
| ubuntu-latest |
1.10.28, 2.2.30, 2.10.3 |
fail |
untested |
| macos-latest |
1.10.28, 2.2.30, 2.10.3 |
fail |
untested |
| windows-latest |
1.10.28, 2.2.30, 2.10.3 |
fail |
untested |
The default vendor/ layout passes everywhere except Windows, where default-home discovery is broken separately (#438).
Probe runs: 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. It reproduces identically with the v4.0.0 release binary (both cases: 0 scanned).
Suspect code
crates/socket-patch-core/src/crawlers/composer_crawler.rs:52-64 (global: composer_home.join("vendor"))
crates/socket-patch-core/src/crawlers/composer_crawler.rs:473-492 (local: no $COMPOSER_HOME/config.json layer)
Activitymikolalysenko commented on Oct 1, 2026 CollaboratorAuthor More actions [agent] Triaged: priority:p2 (Composer). Separate from #438: that one is about finding Composer's home, while this one is about the vendor-dir cascade (COMPOSER_VENDOR_DIR for global, $COMPOSER_HOME/config.json for local) inside that home. No open PR covers it.
Generated by Claude Code mikolalysenko commented on Oct 3, 2026 CollaboratorAuthor More actions [agent] Shares root cause with #686: resolve_local_vendor_dir (and the global get_vendor_paths branch) models only part of Composer's vendor-dir resolution. Missing pieces: the user-level config layer, absolute values, and ~/$HOME expansion. Will be fixed together.
Generated by Claude Code mikolalysenko commented on Oct 12, 2026 CollaboratorAuthor More actions [agent] Claiming this issue (with #686; shared root cause: Composer vendor-dir resolution models only part of Composer's config cascade and path expansion). Branch: agent/fix-composer-vendor-dir-cascade. Claim-ID: 2026-10-12T01:21:01Z-adee5d
Generated by Claude Code mikolalysenko commented on Oct 12, 2026 CollaboratorAuthor More actions added a commit that references this issue on Oct 12, 2026This issue will close once commit 0e87f42 is merged into the 'main' branch.0e87f42
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|