Skip to content

fix(local-fs): Encode object keys to prevent path traversal - #750

Merged
jan-auer merged 3 commits into
mainfrom
worktree-fs-226-local-fs-path-traversal
Nov 5, 2026
Merged

jan-auer merged 3 commits into
mainfrom
worktree-fs-226-local-fs-path-traversal

Conversation

@jan-auer

@jan-auer jan-auer commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

The local filesystem backend joined the object key directly onto the storage root. Keys were never validated, so a key like ../../x could read, write or delete files outside the root. Because each key segment was a plain folder, objects a and a/b also could not both exist.

The backend now builds its own object paths, at {usecase}/{scopes}/objects/{key}.obj. Each /-separated key segment is still one folder level, but it is percent-encoded first:

  • %, ASCII control characters and the characters Windows reserves (\ < > : " | ? *) are escaped.
  • A leading . is escaped, so no segment can be . or ...
  • The . of a trailing .obj is escaped, so a folder can never have the same name as an object file.
  • Empty segments are stored as %.

All other characters, including non-ASCII, are kept as they are, so paths stay readable. Resumable uploads move from uploads/ to .uploads/. A usecase name cannot contain ., so this folder can no longer clash with a usecase called uploads. The module docs now describe the layout, the encoding rules and the remaining limits.
This changes the on-disk layout and there is no migration. Objects stored with the old layout can no longer be read. This is acceptable because there are no self-hosted deployments yet.

Fixes FS-226
Fixes FS-511

Changelog Entry

  • The local filesystem backend now encodes object keys before turning them into file paths. Keys can no longer reach files outside the storage root, and objects such as a and a/b can both exist.

@jan-auer
jan-auer requested a review from a team as a code owner November 3, 2026 11:57
@linear-code

linear-code Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

FS-511

FS-226

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Changelog Preview

This PR lands in these workspaces:

  • objectstore-server: CalVer
📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes

  • The local filesystem backend now encodes object keys before turning them into file paths. Keys can no longer reach files outside the storage root, and objects such as a and a/b can both exist. by jan-auer in #750

🤖 This preview updates automatically when you update the PR.

@codecov

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.87%. Comparing base (dfe0a58) to head (0e86c29).
⚠️ Report is 12 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #750      +/-   ##
==========================================
+ Coverage   91.80%   91.87%   +0.06%     
==========================================
  Files         118      119       +1     
  Lines       22469    22978     +509     
==========================================
+ Hits        20628    21110     +482     
- Misses       1841     1868      +27     
Components Coverage Δ
Rust Backend 94.84% <100.00%> (+0.04%) ⬆️
Rust Client 89.13% <ø> (+1.36%) ⬆️
Python Client 91.64% <ø> (-2.25%) ⬇️

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jan-auer
jan-auer added this pull request to stack #756 November 3, 2026 13:37
@jan-auer
jan-auer force-pushed the worktree-fs-226-local-fs-path-traversal branch from beaa639 to c18e49d Compare November 3, 2026 15:55
Windows strips trailing spaces from names, so a key like `x.obj /y` created a directory that
collided with the object file of key `x`. Escape a trailing space like a trailing dot.

Also use `percent_encode_byte` for escaping instead of formatting by hand.
@jan-auer
jan-auer merged commit 7d411dd into main Nov 5, 2026
27 checks passed
@jan-auer
jan-auer deleted the worktree-fs-226-local-fs-path-traversal branch November 5, 2026 14:17
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.

2 participants