bundler: read path-dependency locations verbatim from the lockfile (#16051)
`Bundler::Source::Path#path` is not the value the lockfile declared. Its
constructor re-relativises the `remote:` against `Bundler.root`, and
`expand_path` clamps `..` at the filesystem root, so any segment that escapes
past `Bundler.root` is dropped rather than preserved:
Bundler.root = /home/dependabot/dependabot-updater (3 segments)
../../../../gems/foo -> ../../../gems/foo # a `..` lost
../../gems/bar -> ../../gems/bar # unchanged
The bundler file fetcher read that mangled value, so a lockfile `PATH` block
reaching further up than the updater's working directory is deep resolved to a
shallower, wrong directory. The gemspec is not found there, and the job aborts
during file fetching with `PathDependenciesNotReachable` naming a gem that is
present and correct in the repo.
The threshold is the depth of `Bundler.root`, which in the updater image is
`/home/dependabot/dependabot-updater`. That makes it an artefact of the
container layout rather than a property of the repository being updated: the
same lockfile can fetch on one image and fail on another, and a lockfile that
resolves under `bundle install` locally can still fail here.
Read `source.options["path"]`, which keeps the lockfile's own value verbatim.
No normalisation is added on top: every consumer of these paths already
normalises, `basename` for the gem name and `repo_contents` /
`fetch_file_from_host` for the requests and the fetched file's name, so a
`./`-prefixed or trailing-slash remote resolves exactly as before.
The regression spec has to stub `Bundler.root`; in a checkout it sits deep
enough that no realistic `remote:` reaches past it, which is why this went
unnoticed. T
Tim Dawborn committed
73ab4307ae2184b2a9e91195859edaf729b8b6f5
Parent: 423dea4
Committed by GitHub <noreply@github.com>
on 8/28/2026, 7:52:03 PM