v1.11.0
1.10.0 tightened upload validation. This release fixes the parts of it that rejected real files, which is the failure operators work around by turning validation off entirely.
Fixed
-
HEIC, MP4, MOV, 3GP and TIFF uploads were rejected under extensions the allowlist accepted. These are ISO base media files, and none of them has a fixed signature at offset 0: what identifies them is the literal
ftypat offset 4, preceded by that box's length. The content check treated the length as part of the signature, pinning0x18for HEIC and MP4 and0x14for 3GP, so a file passed only when its first box happened to be exactly 24 or 20 bytes long. ImageMagick writes0x1Cfor HEIC, ffmpeg writes0x20for MP4, QuickTime writes0x14with aqtbrand, and iPhone HEIC varies by device. All were refused asINVALID_FILE_CONTENT. TIFF had no entry at all and could never pass in either byte order.The family is now identified structurally, by
ftypat offset 4, and TIFF is recognised little- and big-endian. Nothing widens what the service accepts: the extension allowlist is what keeps executable types out, and it is unchanged. -
The MIME type gate rejected valid uploads and stopped nothing.
ValidateFilechecked the multipart part'sContent-Typeagainst an allowlist, but that string is written by the client, so as a gate it never had teeth.application/octet-streamhas to be on any such list because mobile clients send it for everything, and that single entry was a documented bypass. Meanwhile it refused a perfectly good PNG whose part carried noContent-Typeat all, and a PDF announced asapplication/x-pdf. The only workaround available wasVALIDATE_FILE=false, which switches off the two checks that were doing the work.The gate is gone. What rejects a hostile upload is the extension allowlist and the content signature, neither of which the caller controls.
-
An empty
config/tokens.jsonstopped the service from booting. The line that matters is between "no scoped tokens" and "scoped tokens that cannot be read", not between "no file" and "some file". A missing, empty,{}or{"buckets": []}file now boots with zero scoped tokens. Content that cannot be parsed, or an entry that fails validation, still stops boot: there the operator wrote definitions and believes they are live, so starting with fewer credentials than configured would surface as callers getting "invalid token" with nothing to explain it.The general
TOKENis unaffected either way, and is accepted on every route whatever this file contains. -
Placeholder AWS credentials switched the archive on. Copying
.env.exampleleftAWS_ACCESS_KEY_ID=your-aws-keyin place, which is not empty, so the archive reported itself enabled and then failed against a destination that never existed. The shipped placeholders now count as unconfigured.
Added
-
MINIO_VERSIONpins the MinIO server image. Blank still meanslatest, which is fine for a fresh install and not fine for an existing one: MinIO migrates its on-disk format forward and never backward, so an accidental jump is not something you undo by changing the tag back. -
The archive destination is verified at boot when archiving is enabled. Credentials that look valid stay looking valid until something uses them; this makes one real call and reports the result. It runs off the startup path deliberately, so boot never waits on AWS and a transient outage during a restart cannot disable archiving for the life of the process.
Changed
.env.exampleis ordered by how much attention each setting needs, from "nothing works until this is right" down to values you can ignore for years.- The example host nginx config (
cdn.conf) is rewritten: TLS and redirects, the proxy headers the service actually reads, alog_formatthat records the vhost, a cache zone, and anexpiresmap that respects ano-storefrom upstream. Note that caching in front of this service means a deleted object keeps being served until its entry expires, and the open source nginx build has no purge. docs/api.mdand the OpenAPI spec now describe two upload gates rather than three, and list the formats actually accepted. The spec had been advertising "JPG, PNG, GIF, WebP" while the allowlist held 27 extensions.
Upgrading
No configuration change is required and no endpoint contract changed. Uploads that 1.10.0 refused start succeeding; nothing that it accepted is now refused.
If you set VALIDATE_FILE=false to work around rejected uploads, this is the release to set it back to true.