Escape : and % in the signed and cached path and query (closes #247) #269

Merged
clawbot merged 2 commits from issue-247-unambiguous-signed-data into next 2026-10-15 09:37:02 +02:00
Collaborator

Fixes #247.

The signed data and the cache key joined host, path and query with : and no escaping, so path /a:b with no query and path /a with query b: gave the same string. A URL signed for https://h/a:b verified for https://h/a?b:, and the two shared a cached image.

Both now write each % in the path and the query as %25 and each : as %3A before joining them. The host never holds / and the path always starts with /, so the joined string can be read back one way only. A path and query holding neither character are signed and keyed as before, which is why the existing known-answer vectors in internal/signature/golden_test.go and the README example are unchanged. New vectors pin a path with :, a query with :, and a % in both; they were computed outside pixa with openssl dgst -hmac.

Signature Specification in README.md states the escaping. Anyone who signs URLs outside pixa has to apply it to path and query, or a URL whose path or query holds % or : is refused with 401.

  • Judgement call: as the plan says, internal/signature and internal/imgcache each have their own copy of the four-line escaping function, under the same name.
  • Judgement call: the new cache key test sits next to TestCacheKey in storage_internal_test.go; the new signature tests are in a new file, escaping_test.go. No existing test changed.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/pixa/issues/247. The signed data and the cache key joined host, path and query with `:` and no escaping, so path `/a:b` with no query and path `/a` with query `b:` gave the same string. A URL signed for `https://h/a:b` verified for `https://h/a?b:`, and the two shared a cached image. Both now write each `%` in the path and the query as `%25` and each `:` as `%3A` before joining them. The host never holds `/` and the path always starts with `/`, so the joined string can be read back one way only. A path and query holding neither character are signed and keyed as before, which is why the existing known-answer vectors in `internal/signature/golden_test.go` and the README example are unchanged. New vectors pin a path with `:`, a query with `:`, and a `%` in both; they were computed outside pixa with `openssl dgst -hmac`. Signature Specification in `README.md` states the escaping. Anyone who signs URLs outside pixa has to apply it to path and query, or a URL whose path or query holds `%` or `:` is refused with 401. - Judgement call: as the plan says, `internal/signature` and `internal/imgcache` each have their own copy of the four-line escaping function, under the same name. - Judgement call: the new cache key test sits next to `TestCacheKey` in `storage_internal_test.go`; the new signature tests are in a new file, `escaping_test.go`. No existing test changed. Model: opus-5-5
clawbot added the needs-review label 2026-10-15 07:38:43 +02:00
clawbot self-assigned this 2026-10-15 07:38:43 +02:00
clawbot added 2 commits 2026-10-15 07:38:43 +02:00
A URL signed for path /a:b with no query must not verify for path /a with
query b:, and the two must not share a cache key. New known-answer vectors
pin the signature of a path with ":", a query with ":", and a "%" in path
and query, with "%" written as "%25" and ":" as "%3A" in the signed data.
These fail until the fix for
#247 lands.

Model: opus-5-5
The signed data and the cache key joined host, path and query with ":"
and no escaping, so path /a:b with no query and path /a with query b:
gave the same string: a URL signed for one verified for the other, and
whichever was fetched first was served for both. Both now write each "%"
in the path and query as "%25" and each ":" as "%3A" before joining them.
A path and query holding neither are signed and keyed as before.
"Signature Specification" in README.md states the escaping.

Model: opus-5-5
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot merged commit 5d1e3ea871 into next 2026-10-15 09:37:02 +02:00
clawbot deleted branch issue-247-unambiguous-signed-data 2026-10-15 09:37:02 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#269