fix(gitea): escape every value joined into an API path or query #614

Merged
hexajon merged 1 commit from issue-609-escape-path-values into main 2026-09-24 14:11:56 +00:00
Owner

Summary

Most endpoint builders in internal/gitea joined values into the path as raw strings. A ?, #, %, or space in a value could change the endpoint or add a query. The builders now wrap each value in the existing escapePath, which escapes each /-separated part and keeps the /, so a branch feat/x and a file path still work. The release asset upload escapes the file name with url.QueryEscape.

A .. segment could not take a repo-scoped client out of its repo: pathUnderScope already percent-decodes the path and resolves dot-segments before its prefix check.

TestNoUnescapedPathJoins is a guard over the package source. It fails when a path builder joins a value without escapePath (or url.PathEscape, or a strconv number), or joins a query value without url.QueryEscape or url.Values. A line that is plumbing, not a value join, carries a pathjoin:ok comment with its reason (13 lines). With MADTEA_FIX_PATHJOINS=1 set, the same test wraps flagged path values in place; it made the 313 edits here.

TestEscapedValuesReachTheServer checks the result against a test server: a ? and # in a tag name stay in its segment, feat/x keeps its /, and the upload name a b&x=1.zip arrives as one value. Both tests fail when an escape is undone.

Closes #609

Closes #609

## Summary Most endpoint builders in `internal/gitea` joined values into the path as raw strings. A `?`, `#`, `%`, or space in a value could change the endpoint or add a query. The builders now wrap each value in the existing `escapePath`, which escapes each `/`-separated part and keeps the `/`, so a branch `feat/x` and a file path still work. The release asset upload escapes the file name with `url.QueryEscape`. A `..` segment could not take a repo-scoped client out of its repo: `pathUnderScope` already percent-decodes the path and resolves dot-segments before its prefix check. `TestNoUnescapedPathJoins` is a guard over the package source. It fails when a path builder joins a value without `escapePath` (or `url.PathEscape`, or a `strconv` number), or joins a query value without `url.QueryEscape` or `url.Values`. A line that is plumbing, not a value join, carries a `pathjoin:ok` comment with its reason (13 lines). With `MADTEA_FIX_PATHJOINS=1` set, the same test wraps flagged path values in place; it made the 313 edits here. `TestEscapedValuesReachTheServer` checks the result against a test server: a `?` and `#` in a tag name stay in its segment, `feat/x` keeps its `/`, and the upload name `a b&x=1.zip` arrives as one value. Both tests fail when an escape is undone. Closes #609 Closes #609
fix(gitea): escape every value joined into an API path or query
Some checks failed
ci / mcp-conformance (pull_request) Successful in 2m34s
drift / govulncheck (pull_request) Has been skipped
drift / surface-diff (pull_request) Successful in 1m22s
drift / forgejo-smoke (pull_request) Has been skipped
ci / mcp-conformance (push) Successful in 6s
drift / govulncheck (push) Has been skipped
drift / surface-diff (push) Successful in -2s
drift / forgejo-smoke (push) Has been skipped
ci / gate (push) Failing after 20m44s
ci / gate (pull_request) Successful in 35m45s
ec55514a7b
Closes #609
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea!614
No description provided.