fix: inspect uploaded image dimensions on the server
Quality / test (push) Canceled after 0s

This commit is contained in:
2026-09-11 00:35:07 -04:00
parent cce395baf6
commit e6510c0317
11 changed files with 170 additions and 13 deletions
+22 -2
View File
@@ -56,8 +56,10 @@ Validate:
The metadata service currently enforces JPEG, PNG, and WebP MIME types, a
10 MiB default file-size limit, and a 10,000-pixel maximum width and height.
Multipart upload validation now checks the declared MIME type against JPEG,
PNG, and WebP signatures before storage. Image dimensions are supplied by the
upload transport until a decoder-backed dimension extractor is added.
PNG, and WebP signatures before storage. The injected image inspector reads
dimensions and format from the bytes; the service validates those dimensions
and the actual buffer length, then verifies decoding before writing storage or
metadata. Multipart client dimensions are ignored.
Generate:
- thumbnail
@@ -137,3 +139,21 @@ Explicit empty text or null may clear it; missing fields are invalid. The editor
shows the limit, prevents typing past it, and flags oversized pre-existing drafts
until corrected. Legacy absolute sort-order updates require a non-negative
PostgreSQL integer; ordinary Move controls continue using the atomic move API.
## Server-side upload inspection
The production `ImageInspector` uses the existing Sharp dependency behind
`readMetadata(data)` and `validateDecoding(data)` methods. The service checks
actual byte size before inspection, validates the 10,000-pixel dimension limit
against inspected metadata, and only then requests decoding. Sharp rejects
warnings/corruption and has a 100-million-input-pixel ceiling, matching the
maximum permitted dimension product. The tiny decoded output is discarded;
original storage and asynchronous derivatives retain their existing flow.
Malformed or undecodable images return `400 IMAGE_DECODE_INVALID`; format mismatch
uses `IMAGE_SIGNATURE_INVALID`, and inspected dimension violations use
`IMAGE_DIMENSIONS_INVALID`. Rejections happen before storage, metadata, or job
creation. No dependency or database migration is required. The separate JSON
metadata-registration endpoint has no uploaded bytes to inspect and retains its
existing required dimensions; multipart uploads no longer require them.