Commit Graph

7 Commits

Author SHA1 Message Date
c1ec038c99 docs: document cache_max_bytes, update TODO.md (closes #51)
All checks were successful
check / check (push) Successful in 1m40s
Add cache_max_bytes to config.example.yml and the README key settings
list. TODO.md: move cache size management and eviction to Completed
Steps, promote P1 blocked networks configuration into Next Step, and
note in Status that the unbounded disk growth DoS vector is closed.
2026-08-07 21:12:05 +00:00
6573b9d1ef refactor: extract signature package from imgcache (#46)
All checks were successful
check / check (push) Successful in 5s
Extracts HMAC-SHA256 request signing out of `internal/imgcache/` into its own `internal/signature/` package, per the plan in [issue #39](#39).

This is one of the remaining "easily separable" extractions (`imageprocessor`, `allowlist`, `magic`, and `httpfetcher` already landed). Only the signer is moved here so the diff stays reviewable.

## What moved

From `internal/imgcache/signature.go` and its tests into `internal/signature/`:

- `Signer` type, its `New` constructor, `Sign`, `Verify`, `GenerateSignedURL`
- `ParseParams` (query-string signature/expiration parsing)
- Signature error sentinels

## One-way import edge

To keep the import edge one-way (`imgcache` depends on `signature`, never the reverse), the package defines a standalone `Request` type carrying just the fields the signature covers, instead of importing `imgcache.ImageRequest`. `imgcache` projects its `ImageRequest` onto `signature.Request` via a small unexported `signatureRequest` helper. This mirrors how the `magic` extraction defined its own `ImageFormat` type.

## Renames (no stuttering)

- `NewSigner` -> `signature.New`
- `ParseSignatureParams` -> `signature.ParseParams`
- `ErrSignatureRequired`/`Invalid`/`Expired` -> `signature.ErrRequired`/`Invalid`/`Expired`

The `ErrRequired` message is updated from "non-whitelisted host" to "non-allowlisted host" for inclusive terminology, consistent with the `allowlist` rename.

## Rework (post-review)

Three commits added after review feedback:

- `d69019b` — golden known-answer test pinning the exact HMAC signatures and signed URL paths for three fixed vectors (resized, resized+query, orig size), cross-validated against an independent HMAC implementation. Any change to the signed byte format now fails loudly.
- `43b9f1c` — whitelist→allowlist rename completed across `internal/imgcache` and `internal/handlers` (`ServiceConfig.Allowlist`, `Allowlist` interface, `IsAllowlisted`, test helpers and test names).
- `3dc1999` — one-pass config surface rename, no back-compat alias: YAML key `whitelist_hosts` → `allowlist_hosts`, `Config.WhitelistHosts` → `Config.AllowlistHosts`, `config.example.yml`, `scripts/manual-test.sh`, and `README.md` (which also documented a nonexistent `source_host_whitelist` key — now fixed to the real one).

## Behavior

Pure refactor apart from the config key rename above. The bytes fed to the HMAC are unchanged (`host:path:query:width:height:format:expiration`), so previously issued signatures remain valid — now enforced by the golden test. All existing tests move with the package. `script/cibuild` passes at head `3dc1999` (fmt-check, lint, test, build).

refs #39

Co-authored-by: sneak <sneak@sneak.berlin>
Co-authored-by: Jeffrey Paul <sneak@noreply.example.org>
Reviewed-on: #46
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-08-07 17:44:00 +02:00
504afea4f8 scripts-to-rule-them-all (#45)
All checks were successful
check / check (push) Successful in 4s
Reviewed-on: #45
Co-authored-by: sneak <sneak@sneak.berlin>
Co-committed-by: sneak <sneak@sneak.berlin>
2026-07-07 02:14:03 +02:00
a50364bfca Enforce and document exact-match-only for signature verification (#40)
All checks were successful
check / check (push) Successful in 58s
Closes #27

Signatures are per-URL only — this PR adds explicit tests and documentation enforcing that HMAC-SHA256 signatures verify against exact URLs only. No suffix matching, wildcard matching, or partial matching is supported.

## What this does NOT touch

**The host whitelist code (`whitelist.go`) is not modified.** This PR is exclusively about signature verification, per sneak's instructions on [issue #27](#27), [PR #32](#32), and [PR #35](#35).

## Changes

### `internal/imgcache/signature.go`
- Added documentation comments on `Verify()` and `buildSignatureData()` explicitly specifying that signatures are exact-match only — no suffix, wildcard, or partial matching

### `internal/imgcache/signature_test.go`
- **`TestSigner_Verify_ExactMatchOnly`**: 14 tamper cases verifying that modifying any signed component (host, path, query, dimensions, format) causes verification to fail. Host-specific cases include:
  - Parent domain (`example.com`) does not match subdomain signature (`cdn.example.com`)
  - Sibling subdomain (`images.example.com`) does not match
  - Deeper subdomain (`images.cdn.example.com`) does not match
  - Evil suffix domain (`cdn.example.com.evil.com`) does not match
  - Prefixed host (`evilcdn.example.com`) does not match
- **`TestSigner_Sign_ExactHostInData`**: Verifies that suffix-related hosts (`cdn.example.com`, `example.com`, `images.example.com`, etc.) all produce distinct signatures

### `internal/imgcache/service_test.go`
- **`TestService_ValidateRequest_SignatureExactHostMatch`**: Integration test through `ValidateRequest` verifying that a valid signature for `cdn.example.com` is rejected when presented with a different host (parent domain, sibling subdomain, deeper subdomain, evil suffix, prefixed host)

### `README.md`
- Updated Signature Specification section to explicitly document exact-match-only semantics

Co-authored-by: user <user@Mac.lan guest wan>
Reviewed-on: #40
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-03-20 23:56:45 +01:00
73f1073d61 chore: restructure README with required policy sections 2026-02-25 19:47:34 +07:00
27eb9fb513 Add HMAC signature specification to README
Documents the signature scheme: HMAC-SHA256 over host:path:query:width:height:format:expiration
with base64url encoding and Unix timestamp expiration.
2026-01-08 03:35:36 -08:00
6071fd5bb7 Add project documentation and linter config 2026-01-08 02:18:45 -08:00