fix(image-downloader): detect media type from magic bytes instead of URL extension#1280
Open
bakrsabeeh wants to merge 1 commit intoanthropics:mainfrom
Open
fix(image-downloader): detect media type from magic bytes instead of URL extension#1280bakrsabeeh wants to merge 1 commit intoanthropics:mainfrom
bakrsabeeh wants to merge 1 commit intoanthropics:mainfrom
Conversation
…tension Fixes 400 API errors when GitHub serves images with mismatched extensions (e.g. Claude's own spinner GIF downloaded as .png). Now reads the first 12 bytes of each downloaded buffer to identify the real format before saving the file. Fixes anthropics#702, anthropics#495
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix: Detect image media type from magic bytes instead of file extension
Problem
When Claude Code Action downloads images from GitHub comments, it determines
the
media_typefield (sent to the Anthropic API) from the file extensionin the URL — not from the actual file content.
This causes a
400 invalid_request_errorwhenever the real format doesn'tmatch the extension. The most common trigger is Claude's own spinner GIF,
which the action adds to comments during processing and then downloads back
as
/tmp/github-images/image-xxx-0.png. Because the file is saved as.pngbut contains GIF bytes, the API rejects it with:
Fixes: #702, #495
Related issues in
claude-code: #13396, #30124, #31642, #39146, #11931Root cause
src/github/image-downloader.tscontained two functions:The downloaded file was also saved with the URL-derived extension (e.g.
.png), so even checking the saved filename would reproduce the same error.Fix
Replace extension-based detection with magic byte sniffing:
.binextension — no format assumption.detectMediaTypeFromBytes(buffer)reads the first 12 bytes of the file andmatches against known signatures:
\x89PNG\r\n\x1a\n(8 bytes)\xFF\xD8\xFF(3 bytes)GIF87a(6 bytes)GIF89a(6 bytes)RIFF????WEBP(bytes 0-3 + 8-11)getMediaType(filePath)opens the file, reads 12 bytes, callsdetectMediaTypeFromBytes, and falls back to extension-based detectiononly when the magic bytes are inconclusive.
Only 12 bytes are read per file — zero performance impact.
Files changed
src/github/image-downloader.ts— core fix (magic byte detection)Tests
Unit tests cover:
.pngfile → correctly returnsimage/gif.pngfile → correctly returnsimage/jpeg.jpgfile → correctly returnsimage/webpimage/pngwhen both magic bytes and extension are unknownnull