Skip to content

Escape delegated role name when reading cached metadata#755

Open
sueun-dev wants to merge 1 commit into
theupdateframework:masterfrom
sueun-dev:fix-delegated-cache-escape
Open

Escape delegated role name when reading cached metadata#755
sueun-dev wants to merge 1 commit into
theupdateframework:masterfrom
sueun-dev:fix-delegated-cache-escape

Conversation

@sueun-dev

Copy link
Copy Markdown

loadTargets reads cached delegated metadata from filepath.Join(LocalMetadataDir, roleName), but persistMetadata writes it under url.PathEscape(roleName). When a delegated role name contains a character PathEscape rewrites (a space, /, %, ...), the read and write paths differ, so the cached file is never found and the role's metadata is re-downloaded on every refresh. A name like .. also makes the read resolve outside LocalMetadataDir.

The escape landed on the write and download paths in #675, but the delegated read still used the raw name.

What changed:

  • Added localMetadataPath and used it for both the write in persistMetadata and the delegated read in loadTargets, so the two always agree on the file name. Appending .json before the join keeps a . or .. name inside the metadata directory.
  • Added a test that persists and reads back metadata for role names containing a space, /, ., .., and %.

Checked:

  • GODEBUG=rsa1024min=0 go test ./metadata/...
  • go vet ./...

persistMetadata writes cached metadata under url.PathEscape(roleName),
but loadTargets read it back using the raw role name. A delegated role
whose name contains a character PathEscape rewrites (a space, "/", ...)
was therefore never found in the cache and re-downloaded on every
refresh, and a name like ".." resolved outside LocalMetadataDir.

Share a single localMetadataPath helper between the write and the
delegated read so the two agree on the file name. The ".json" suffix is
added before the join so a "." or ".." name stays inside the directory.

Signed-off-by: Sueun Cho <sueun.dev@gmail.com>
@sueun-dev
sueun-dev requested a review from a team as a code owner July 13, 2026 16:12
Copilot AI review requested due to automatic review settings July 13, 2026 16:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes delegated-targets cache misses (and potential path traversal) by ensuring delegated role names are consistently URL-escaped for both cache writes and reads, so cached metadata is found even when role names contain special characters.

Changes:

  • Introduced localMetadataPath and used it in both persistMetadata and delegated-role cache reads in loadTargets.
  • Updated delegated-role cache read to use the escaped filename (matching the write path).
  • Added a round-trip test covering delegated role names with spaces, /, ., .., and %.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
metadata/updater/updater.go Aligns delegated cached-metadata read path with the existing escaped write path via a shared helper.
metadata/updater/updater_delegated_cache_test.go Adds coverage for escaped delegated-role cache filenames, including edge-case role names.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

assert.Equal(t, dir, filepath.Dir(path))
assert.Equal(t, url.PathEscape(roleName)+".json", filepath.Base(path))

// The read loadTargets performs recovers the persisted bytes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants