[v5.0] fix(provider-utils): bound media-type sniffing decode for ID3-prefixed input - #17746
Conversation
Bugfix reviewOutcome: approved Fixes issueStatus: fully-addresses The implementation limits base64 decoding to a fixed prefix, uses zero-copy Uint8Array subarray views, handles ID3 from decoded bytes, preserves detection at the inclusive 128 KiB boundary, and returns undefined beyond it. Side effectsRisk: low Normal non-ID3 signature detection remains limited to the existing 18-byte prefix. The only deliberate behavior change is that oversized ID3 tags are no longer scanned to their trailing media signature. PerformanceRisk: low ID3 processing now performs attachment-size-independent work: base64 decoding is capped at roughly 128 KiB and raw input is viewed through subarray rather than copied. Backwards compatibilityRisk: low The change does not mutate or migrate stored data. It only changes runtime auto-detection for ID3 tags beyond the documented scan limit, where callers can continue supplying an explicit media type. ArchitectureRisk: low The fix remains localized in the v5 ai package's existing media-detection utility, uses provider-utils through its declared public package export, and introduces no cross-package src imports or inappropriate shared abstractions. Change scopeStatus: minimal The three changed files are limited to the detection implementation, focused boundary regression tests, and the required patch changeset. SecurityRisk: low The change reduces denial-of-service exposure from crafted ID3-prefixed attachments and uses clamping subarray operations for malformed or oversized size fields without adding new trust boundaries. TestingStatus: appropriate Tests cover raw and base64 MP3 detection at and immediately beyond the 128 KiB boundary. The complete 48-test media-detection suite passed in both Node and edge configurations, and focused verification also covered bounded decoding, zero raw slicing, malformed sizes, combined signatures, and normalized input forms. VerificationReviewed every merge-base diff hunk, confirmed clean diff formatting and package boundaries, passed the ai package type-check, passed all 48 media-detection tests in Node and edge environments, and independently verified bounded decoding and raw-copy behavior across boundary, malformed, image, audio, combined, base64url, data URL, ArrayBuffer, Buffer, and text cases. Relevant Documentation |
|
🚀 Published in:
|
Summary
Media-type sniffing is documented as an O(1) check on the first ~18 bytes (24 base64 chars). An
ID3/SUQz-prefixed attachment bypassed that bound:stripID3TagsIfPresentran before the truncation and decoded the entire base64 attachment (plus a full-size.slice()copy), then returned aUint8Arrayso the 24-char cap was skipped. A 4-character prefix flipped intended O(1) sniffing into an O(N) decode + copy of the whole attachment, on every path including image detection.Hardening
ID3) instead of the base64 string (startsWith('SUQz')), so string and raw-byte inputs are checked uniformly and base64 alignment tricks cannot fool it.Uint8Arraypath is bounded too, andstripID3usessubarray(a view) instead ofslice(a full copy), removing the second O(N) copy.ID3_MAX_SCAN_BYTES(128 KB), large enough to cover typical tags with embedded cover art while keeping cost constant in attachment size.Happy path
audio/mpeg.data:URLs, base64url,ArrayBuffer,Buffer, andtextinputs are normalized upstream and behave the same.Unhappy path
ID3/SUQz-prefixed attachment (benign or crafted) now decodes at most ~128 KB regardless of attachment size, so sniffing stays constant-time instead of scaling with the input.resolveFullMediaTypethrows its existing "must specify subtype" error if none was provided). RaiseID3_MAX_SCAN_BYTESif larger tags must be detected; cost stays O(1) either way.id3Sizecannot read out of bounds:subarrayclamps to length and returns empty, so no signature matches and detection returnsundefined.Testing
detect-media-typesuite passes (67 tests).Fixes #17709
Related Issues
Backport of #17386