HandleImageEnc (internal/handlers/imageenc.go:49-50) builds the image request straight from the decrypted payload:
req:=payload.ToImageRequest()
Unlike the /v1/image/ path, nothing between decryption and processing applies:
the MaxDimension bound enforced by internal/imgcache/urlparser.go:24,224-226
ValidateFitMode
The token generator is equally lax: HandleGenerateURL (internal/handlers/auth.go:106-108) runs strconv.Atoi on width, height, quality, and ttl and discards every error, so non-numeric input silently becomes 0, and no upper bound is applied to width/height.
Consequences:
A generated token can request e.g. 100000x100000, which reaches libvips and blows up memory — the same class of resource exhaustion the /v1/image/ path already guards against.
An invalid fit mode reaches imageprocessor.resize's default branch (internal/imageprocessor/imageprocessor.go:326-328) and surfaces as a 500 rather than a 400.
This requires the signing key to exploit (the payload is sealed), so it is self-inflicted rather than remotely exploitable — but "the operator can trivially DoS their own daemon through the supplied web UI, and gets a 500 for a validation error" is not 1.0 behavior, and the asymmetry with /v1/image/ is exactly the kind of thing that rots.
Related but filed separately: repo policy forbids silently defaulting an invalid explicit value. strconv.Atoi errors becoming 0 is that defect in the handler layer.
Definition of done
/v1/e/ applies the same dimension bound and fit-mode validation as /v1/image/, sharing the validation code rather than duplicating it.
HandleGenerateURL checks every strconv.Atoi error and rejects bad input with a 400 naming the offending field, instead of coercing to 0. Width/height are bounds-checked at generation time too, so an unusable token cannot be minted.
An invalid fit mode produces a 400, not a 500, on both routes.
Failing tests first: an encrypted token carrying an over-limit dimension is rejected; one carrying an invalid fit mode returns 400; POST /generate with non-numeric width returns 400 rather than generating a 0-width token.
make check green.
Verified against `main` at `61f42e6`.
`HandleImageEnc` (`internal/handlers/imageenc.go:49-50`) builds the image request straight from the decrypted payload:
```go
req := payload.ToImageRequest()
```
Unlike the `/v1/image/` path, nothing between decryption and processing applies:
- the `MaxDimension` bound enforced by `internal/imgcache/urlparser.go:24,224-226`
- `ValidateFitMode`
The token generator is equally lax: `HandleGenerateURL` (`internal/handlers/auth.go:106-108`) runs `strconv.Atoi` on `width`, `height`, `quality`, and `ttl` and **discards every error**, so non-numeric input silently becomes `0`, and no upper bound is applied to width/height.
Consequences:
- A generated token can request e.g. 100000x100000, which reaches libvips and blows up memory — the same class of resource exhaustion the `/v1/image/` path already guards against.
- An invalid fit mode reaches `imageprocessor.resize`'s default branch (`internal/imageprocessor/imageprocessor.go:326-328`) and surfaces as a 500 rather than a 400.
This requires the signing key to exploit (the payload is sealed), so it is self-inflicted rather than remotely exploitable — but "the operator can trivially DoS their own daemon through the supplied web UI, and gets a 500 for a validation error" is not 1.0 behavior, and the asymmetry with `/v1/image/` is exactly the kind of thing that rots.
Related but filed separately: repo policy forbids silently defaulting an invalid explicit value. `strconv.Atoi` errors becoming `0` is that defect in the handler layer.
## Definition of done
1. `/v1/e/` applies the same dimension bound and fit-mode validation as `/v1/image/`, sharing the validation code rather than duplicating it.
2. `HandleGenerateURL` checks every `strconv.Atoi` error and rejects bad input with a 400 naming the offending field, instead of coercing to `0`. Width/height are bounds-checked at generation time too, so an unusable token cannot be minted.
3. An invalid fit mode produces a 400, not a 500, on both routes.
4. Failing tests first: an encrypted token carrying an over-limit dimension is rejected; one carrying an invalid fit mode returns 400; `POST /generate` with non-numeric width returns 400 rather than generating a `0`-width token.
5. `make check` green.
clawbot
added this to the 1.0.0 milestone 2026-08-09 03:43:23 +02:00
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.
Verified against
mainat61f42e6.HandleImageEnc(internal/handlers/imageenc.go:49-50) builds the image request straight from the decrypted payload:Unlike the
/v1/image/path, nothing between decryption and processing applies:MaxDimensionbound enforced byinternal/imgcache/urlparser.go:24,224-226ValidateFitModeThe token generator is equally lax:
HandleGenerateURL(internal/handlers/auth.go:106-108) runsstrconv.Atoionwidth,height,quality, andttland discards every error, so non-numeric input silently becomes0, and no upper bound is applied to width/height.Consequences:
/v1/image/path already guards against.imageprocessor.resize's default branch (internal/imageprocessor/imageprocessor.go:326-328) and surfaces as a 500 rather than a 400.This requires the signing key to exploit (the payload is sealed), so it is self-inflicted rather than remotely exploitable — but "the operator can trivially DoS their own daemon through the supplied web UI, and gets a 500 for a validation error" is not 1.0 behavior, and the asymmetry with
/v1/image/is exactly the kind of thing that rots.Related but filed separately: repo policy forbids silently defaulting an invalid explicit value.
strconv.Atoierrors becoming0is that defect in the handler layer.Definition of done
/v1/e/applies the same dimension bound and fit-mode validation as/v1/image/, sharing the validation code rather than duplicating it.HandleGenerateURLchecks everystrconv.Atoierror and rejects bad input with a 400 naming the offending field, instead of coercing to0. Width/height are bounds-checked at generation time too, so an unusable token cannot be minted.POST /generatewith non-numeric width returns 400 rather than generating a0-width token.make checkgreen.