Skip to content

Hash path-based metadata cache keys - #578

Merged
andrew merged 3 commits into
git-pkgs:mainfrom
simonchrz:fix/unambiguous-metadata-keys
Oct 25, 2026
Merged

andrew merged 3 commits into
git-pkgs:mainfrom
simonchrz:fix/unambiguous-metadata-keys

Conversation

@simonchrz

Copy link
Copy Markdown
Contributor

Conan, CRAN, Conda, RPM, the main Debian archive and the default Maven repository keyed cached metadata by the request path with / replaced by _. Conan names and versions may contain _, so foo/bar_1.0 and foo_bar/1.0 shared a cache entry, and with cache_metadata: true one reference's latest or recipe files were served for the other. Conan also appended the query with _, so /v2/conans/search?q=x and /v2/conans/search_q=x shared one too. The same can happen in the other ecosystems wherever _ appears in a path.

These keys are now a hash of the upstream URL, the path and, for Conan, the query, as the APK, Arch, generic and Helm handlers already do. The parts are length-prefixed before hashing so no two inputs share a key. Including the upstream URL also means repointing an upstream no longer serves what the old one cached.

Metadata cached under the old keys is not read any more and is simply fetched again on the next request. The old rows and files stay in storage; with a cache size limit, eviction removes them as least recently used, otherwise they stay until the cache is cleared. Debian's artifact filenames are unchanged.

A second commit adds the ?/# check that Arch and FreeBSD already do to the Debian, RPM, APK, PyPI, CRAN and Maven handlers. They build upstream URLs from the decoded path and relied only on the server middleware to refuse these characters.

Tests: TestConanMetadataKeysKeepReferencesApart requests colliding Conan paths through the handler and checks each gets its own response; TestMetadataCacheKeysUnambiguous covers the other handlers' keys; TestHandlersRejectQueryCharsInPath sends encoded ? and # to each handler directly. All three fail without the changes.

@andrew

andrew commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

This conflicts with main in internal/handler/conda.go since the conda shards change merged. Could you rebase?

Conan, CRAN, Conda, RPM, the main Debian archive and the default Maven
repository keyed cached metadata by the request path with '/' replaced
by '_'. Names and versions may contain '_', so foo/bar_1.0 and
foo_bar/1.0 shared an entry, and with cache_metadata one reference's
recipe files were served for the other. Conan also appended the query
with '_', so a path without a query could collide with a shorter path
plus one.

Hash the upstream URL, the path and, for Conan, the query instead, as
the APK, Arch, generic and Helm handlers already do. Each part is
length-prefixed so no two inputs share a key.
Debian, RPM, APK, PyPI, CRAN and Maven build upstream URLs from the
decoded request path, where a '?' or '#' would end the path and cache
one file under another's name. Only the server middleware refused them;
Arch and FreeBSD also check in the handler. Check in these handlers
too, so they stay safe when mounted without the middleware.
@simonchrz
simonchrz force-pushed the fix/unambiguous-metadata-keys branch from 80409a9 to d64bfc6 Compare October 24, 2026 11:03
@simonchrz

Copy link
Copy Markdown
Contributor Author

Rebased onto main, CI is green.

@simonchrz

Copy link
Copy Markdown
Contributor Author

The conda shards change added a second /→_ key (condaCacheKey); the shard routes now use the hashed key too.

@andrew
andrew merged commit 560a991 into git-pkgs:main Oct 25, 2026
7 checks passed
@simonchrz simonchrz added the breaking Changes behaviour users rely on; needs a minor release label Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Changes behaviour users rely on; needs a minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants