🚫 fix: Decline to Name a Heif Container With Unreported Compression (#15612)

`resolveImageMimeType` returned `image/heic` for any heif container whose
compression was not `av1`, which included the case where sharp reported no
compression at all. `Metadata.compression` is optional, so unreported is a real
outcome, and answering it with HEIC is a guess — an AVIF read back without its
compression would be recorded as HEIC.

That is the failure #15606 exists to prevent, reproduced inside the fix for it,
and it contradicted the documented contract of returning `undefined` rather than
naming bytes that cannot be identified.

Unreported or unrecognized compression now yields `undefined`, which leaves
`saveBase64Image` on the declared type: still only a claim, but the caller's
claim rather than one invented here.
This commit is contained in:
Danny Avila 2026-09-04 13:50:02 -04:00 • committed by GitHub
parent c13990a398
commit 3200f0133a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 12 additions and 3 deletions

View file

@ -40,4 +40,9 @@ describe('resolveImageMimeType', () => {
expect(resolveImageMimeType({ format: 'svg' })).toBeUndefined();
expect(resolveImageMimeType({ format: 'raw' })).toBeUndefined();
});
it('declines to name a heif container whose compression sharp did not report', () => {
expect(resolveImageMimeType({ format: 'heif' })).toBeUndefined();
expect(resolveImageMimeType({ format: 'heif', compression: undefined })).toBeUndefined();
});
});

View file

@ -27,8 +27,9 @@ export type EncodedImageMetadata = Pick<Metadata, 'format' | 'compression'>;
* bytes leaves a file whose `type` misdescribes its own contents, and that type is later handed
* to providers verbatim as `media_type`/`mimeType`, so it has to describe the bytes on disk.
*
* Returns `undefined` when sharp reports a format with no media type of its own, leaving the
* caller to decide what to record rather than guessing here.
* Returns `undefined` when the bytes cannot be named confidently — a format with no media type of
* its own, or a heif container whose compression sharp did not report — leaving the caller to fall
* back to what it already knows. Naming one of those anyway would be the guess this exists to stop.
*/
export function resolveImageMimeType(metadata: EncodedImageMetadata): string | undefined {
const { format } = metadata;
@ -36,7 +37,10 @@ export function resolveImageMimeType(metadata: EncodedImageMetadata): string | u
return undefined;
}
if (format === 'heif') {
return metadata.compression === 'av1' ? 'image/avif' : 'image/heic';
if (metadata.compression === 'av1') {
return 'image/avif';
}
return metadata.compression === 'hevc' ? 'image/heic' : undefined;
}
return SHARP_FORMAT_MIME_TYPES[format];
}