Skip to content

Contain filesystem store paths to the configured base path - #58

Open
damilolaedwards wants to merge 1 commit into
ethpandaops:masterfrom
damilolaedwards:fix/contain-filesystem-store-paths
Open

Contain filesystem store paths to the configured base path#58
damilolaedwards wants to merge 1 commit into
ethpandaops:masterfrom
damilolaedwards:fix/contain-filesystem-store-paths

Conversation

@damilolaedwards

Copy link
Copy Markdown

Summary

FSStore built disk paths by joining the configured base path with a caller-supplied location, with nothing stopping that location from containing ".." segments and resolving outside the base path entirely. Locations are accepted from callers without any format validation upstream, so a crafted location could read, write, or delete arbitrary files on the host, reachable through the same download and retention code paths that handle ordinary records.

Every method that turns a location into a filesystem path now routes through a single resolve helper that rejects anything which would land outside the base path, returning the existing ErrInvalid sentinel. Legitimate nested locations are unaffected.

This is fixed at the store layer rather than only at the gRPC ingestion point, so every current and future caller of FSStore gets the containment guarantee automatically, regardless of what validation happens upstream.

Changes

  • pkg/store/fs.go: added resolve(), used by Exists, all six data types' Save*/Get*/Delete*, the storage handshake token methods, and Copy (both source and destination)
  • pkg/store/fs_test.go: new test covering several traversal payloads rejected across Exists/Get/Delete/Save/Copy, plus a check that ordinary nested locations still work exactly as before

Test plan

  • go build ./... and go vet ./... pass
  • New traversal tests pass
  • Existing TestFSStoreOperations suite (17 subtests) still passes unchanged
  • Traced download.go and retention.go to confirm they already handle a store error safely (no changes needed there)

FSStore built disk paths by joining the base path with a caller
supplied location, with nothing stopping that location from
containing ".." segments and resolving outside the base path
entirely. Since a location is accepted from callers without any
format validation upstream, this meant a crafted location could read,
write, or delete arbitrary files on the host, reachable through the
same download and retention code paths that handle ordinary records.

Every method that turns a location into a filesystem path now routes
through a single resolve helper that rejects anything which would
land outside the base path, returning the existing ErrInvalid
sentinel. Legitimate nested locations are unaffected.
@damilolaedwards
damilolaedwards requested a review from Savid as a code owner July 25, 2026 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant