Skip to content

Refuse a download path that climbs out of /user_uploads - #380

Merged
GraemeF merged 1 commit into
mainfrom
comms-at1hw
Oct 22, 2026
Merged

GraemeF merged 1 commit into
mainfrom
comms-at1hw

Conversation

@GraemeF

@GraemeF GraemeF commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

An upload path was accepted on its /user_uploads/ prefix alone. The HTTP client resolves dot segments, their percent-encoded forms and backslashes before it sends, so a path such as /user_uploads/../api/v1/users reached an API endpoint with the minter's credentials. Any agent could pass such a path through download_file.

The upload-path brand now accepts only a path that URL parsing leaves unchanged once decoded, and whose segments decode to no separator. The adapter and the tool both decode through the brand, so a refused path sends no request.

The shared attachment contract now tries those climbs and checks that a non-ASCII filename still downloads. For the second test to match Zulip, the in-process realm now keeps Unicode word characters in upload names as Zulip's sanitize_name does, and decodes a request path before routing it.

An upload path was accepted on its /user_uploads/ prefix alone. The HTTP
client resolves dot segments, their percent-encoded forms and backslashes
before it sends, so a path such as /user_uploads/../api/v1/users reached an
API endpoint with the minter's credentials. The upload-path brand now accepts
only a path that URL parsing leaves unchanged once decoded, and whose segments
decode to no separator. Both the adapter's downloadFile and the download_file
tool decode through it, so a refused path sends no request.

The shared attachment contract now tries those climbs, plainly written and
percent-encoded, and checks that a file with a non-ASCII name still
downloads. To make that second test mean what it does on Zulip, the
in-process realm now sanitises upload names the way Zulip does, keeping
Unicode word characters, and decodes a request path before it routes it.
@GraemeF
GraemeF merged commit 6ead983 into main Oct 22, 2026
2 checks passed
@GraemeF
GraemeF deleted the comms-at1hw branch October 22, 2026 17:18
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