← All issues

Untrusted image data restricted from ImageIO codec dispatch in WebExtension icon loading

b9c7a1b

ImageIO on Apple platforms selects a codec by inspecting the first few magic bytes of input, and [NSImage initWithData] delegates this dispatch unconditionally — any system-registered codec can be invoked on attacker-supplied bytes, including exotic formats like PSD, OpenEXR, and raw TIFF. WebExtension icons load in the UIProcess, which is not sandbox-restricted like WebContent, so codec vulnerabilities there are higher impact.

Source/WebKit/Platform/cocoa/CocoaImage.mm

+RetainPtr<CocoaImage> createCocoaImageRestrictedToSupportedTypes(NSData *data, double displayScale)
+{
+ RetainPtr imageSource = adoptCF(CGImageSourceCreateWithData((__bridge CFDataRef)data, nullptr));
+ if (!imageSource)
+ return nil;
+ RetainPtr type = CGImageSourceGetType(imageSource.get());
+ if (!type || !WebCore::isSupportedImageType(type.get()))
+ return nil;
+ RetainPtr image = adoptCF(CGImageSourceCreateImageAtIndex(imageSource.get(), 0, nullptr));
+ ...
+}

The fix replaces [NSImage initWithData] with a three-stage approach: detect type via CGImageSourceGetType, gate against WebCore::isSupportedImageType() (the same allowlist used for web content), then decode with CGImageSourceCreateImageAtIndex. SVG bypasses the CoreGraphics path and is handled separately via _NSSVGImageRep on macOS and CoreSVG on iOS.

This restricts codec dispatch in the highest-value process to the same allowlist used for web content, closing the door on attacker-controlled magic bytes invoking rarely-audited ImageIO decoders (PSD, OpenEXR, TIFF) unsandboxed.

The SVG branch triggers on resourceMIMETypeForPath(imagePath) — a path/extension heuristic, not a magic-byte check. An attacker who controls the icon path in the extension manifest can name any file .svg to route its bytes into [_NSSVGImageRep initWithData] (macOS) or [UIImage _imageWithCGSVGDocument] (iOS), entirely bypassing the isSupportedImageType allowlist; both are private APIs with minimal public fuzzing coverage, running unsandboxed in the UIProcess. Separately, the hardening is only as strong as the allowlist — audit WebCore/UTIRegistry.cpp to enumerate what passes the gate, since any allowed type with complex multi-frame or metadata parsing (TIFF, JPEG 2000) is a candidate for targeted fuzzing.