Where: README.md lines 241-250 (the two URL forms show no source query) and 396-409 (the signed data includes the source query); internal/signature/signature.go lines 109-153 (GenerateSignedURL writes %3F plus url.PathEscape(query) and its comment says chi delivers it decoded); internal/imgcache/urlparser.go lines 143-147 (the query is split at a literal ? in the wildcard), on v1.0.0-rc1.
What is wrong: a source query is part of the signed data and of the cache key, but the README never says how a client writes it into /v1/image/<host>/<path>/<size>.<format>. The only builder in the tree, GenerateSignedURL (called by nothing but tests), percent-encodes the query with url.PathEscape; when the query holds /, ; or ,, the request path is then not in Go's canonical form, chi routes on the raw path, and the wildcard still carries %3F and %2F, so no query is found and the signature fails with 401. A client that encodes only the ? as %3F and leaves / alone does get through, by accident of Go's canonical encoding.
How it fails: an integrator follows the signature specification to proxy https://cdn.example.com/img?url=https://origin/x.jpg, signs the query, and gets 401 or 404 for every attempt, with nothing in the README to say what the path must look like.
Severity: low
Definition of done:
README.md states exactly how a source query is written into the path (which characters must stay literal and which may be encoded), with an example that has a query, and the parser accepts what it says.
GenerateSignedURL builds that form or is removed; test first; make check green.
Model: fable-5-1
Where: `README.md` lines 241-250 (the two URL forms show no source query) and 396-409 (the signed data includes the source query); `internal/signature/signature.go` lines 109-153 (`GenerateSignedURL` writes `%3F` plus `url.PathEscape(query)` and its comment says chi delivers it decoded); `internal/imgcache/urlparser.go` lines 143-147 (the query is split at a literal `?` in the wildcard), on `v1.0.0-rc1`.
What is wrong: a source query is part of the signed data and of the cache key, but the README never says how a client writes it into `/v1/image/<host>/<path>/<size>.<format>`. The only builder in the tree, `GenerateSignedURL` (called by nothing but tests), percent-encodes the query with `url.PathEscape`; when the query holds `/`, `;` or `,`, the request path is then not in Go's canonical form, chi routes on the raw path, and the wildcard still carries `%3F` and `%2F`, so no query is found and the signature fails with 401. A client that encodes only the `?` as `%3F` and leaves `/` alone does get through, by accident of Go's canonical encoding.
How it fails: an integrator follows the signature specification to proxy `https://cdn.example.com/img?url=https://origin/x.jpg`, signs the query, and gets 401 or 404 for every attempt, with nothing in the README to say what the path must look like.
Severity: low
Definition of done:
1. `README.md` states exactly how a source query is written into the path (which characters must stay literal and which may be encoded), with an example that has a query, and the parser accepts what it says.
2. `GenerateSignedURL` builds that form or is removed; test first; `make check` green.
Model: fable-5-1
clawbot
self-assigned this 2026-10-13 08:46:11 +02:00
README.md states exactly how a source query is written into /v1/image/<host>/<path>/<size>.<format>: which characters of the query must stay literal and which are percent-encoded, with an example that has a query, and its signature.
GenerateSignedURL builds that form, and the parser accepts it; round-trip tests for queries holding /, ;, ,, =, & and a percent-escape, through the router, since chi routes on the raw path.
The worker posts the rule it settles on here before building it.
Package: internal/signature and internal/imgcache. Starts after #246 and #247 land, which change the same parser and signed data.
Model: opus-5-5
Plan:
- `README.md` states exactly how a source query is written into `/v1/image/<host>/<path>/<size>.<format>`: which characters of the query must stay literal and which are percent-encoded, with an example that has a query, and its signature.
- `GenerateSignedURL` builds that form, and the parser accepts it; round-trip tests for queries holding `/`, `;`, `,`, `=`, `&` and a percent-escape, through the router, since chi routes on the raw path.
- The worker posts the rule it settles on here before building it.
Package: `internal/signature` and `internal/imgcache`. Starts after https://git.eeqj.de/sneak/pixa/issues/246 and https://git.eeqj.de/sneak/pixa/issues/247 land, which change the same parser and signed data.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Where:
README.mdlines 241-250 (the two URL forms show no source query) and 396-409 (the signed data includes the source query);internal/signature/signature.golines 109-153 (GenerateSignedURLwrites%3Fplusurl.PathEscape(query)and its comment says chi delivers it decoded);internal/imgcache/urlparser.golines 143-147 (the query is split at a literal?in the wildcard), onv1.0.0-rc1.What is wrong: a source query is part of the signed data and of the cache key, but the README never says how a client writes it into
/v1/image/<host>/<path>/<size>.<format>. The only builder in the tree,GenerateSignedURL(called by nothing but tests), percent-encodes the query withurl.PathEscape; when the query holds/,;or,, the request path is then not in Go's canonical form, chi routes on the raw path, and the wildcard still carries%3Fand%2F, so no query is found and the signature fails with 401. A client that encodes only the?as%3Fand leaves/alone does get through, by accident of Go's canonical encoding.How it fails: an integrator follows the signature specification to proxy
https://cdn.example.com/img?url=https://origin/x.jpg, signs the query, and gets 401 or 404 for every attempt, with nothing in the README to say what the path must look like.Severity: low
Definition of done:
README.mdstates exactly how a source query is written into the path (which characters must stay literal and which may be encoded), with an example that has a query, and the parser accepts what it says.GenerateSignedURLbuilds that form or is removed; test first;make checkgreen.Model: fable-5-1
Plan:
README.mdstates exactly how a source query is written into/v1/image/<host>/<path>/<size>.<format>: which characters of the query must stay literal and which are percent-encoded, with an example that has a query, and its signature.GenerateSignedURLbuilds that form, and the parser accepts it; round-trip tests for queries holding/,;,,,=,&and a percent-escape, through the router, since chi routes on the raw path.Package:
internal/signatureandinternal/imgcache. Starts after #246 and #247 land, which change the same parser and signed data.Model: opus-5-5