Gateway: follow up HEIC input image handling#38146
Conversation
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 MIME type spoofing allows non-image content to bypass image MIME allowlist in normalizeInputImage
Description
This enables content-type confusion / validation bypass:
Vulnerable behavior introduced in this change:
RecommendationDo not rely on a declared MIME type for security decisions. Mitigations (choose one depending on desired strictness/perf):
const declaredMime = normalizeMimeType(params.mimeType) ?? "application/octet-stream";
const detected = normalizeMimeType(await detectMime({ buffer: params.buffer, headerMime: params.mimeType }));
// If we can detect a concrete type, prefer it.
const sourceMime = detected ?? declaredMime;
// Optional hardening: if declared claims image/* but detected is a non-image, reject.
if (declaredMime.startsWith("image/") && detected && !detected.startsWith("image/")) {
throw new Error(`Invalid image content: detected ${detected} for declared ${declaredMime}`);
}
if (!params.limits.allowedMimes.has(sourceMime)) {
throw new Error(`Unsupported image MIME type: ${sourceMime}`);
}
Also consider logging/auditing mismatches ( Analyzed PR: #38146 at commit Last updated on: 2026-03-06T17:02:22Z |
Greptile SummaryThis PR is a targeted follow-up to the HEIC
Test coverage is comprehensive and hermetic:
CHANGELOG entry (line 141) accurately documents the follow-up changes. Confidence Score: 5/5
Last reviewed commit: 3552736 |
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix (cherry picked from commit 9521e61)
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix (cherry picked from commit 9521e61)
* Media: scope HEIC MIME sniffing * Media: hermeticize HEIC input tests * Gateway: fix HEIC image budget accounting * Gateway: add HEIC image budget regression test * Changelog: note HEIC follow-up fix (cherry picked from commit 9521e61)
Summary
input_imagePR introduced two follow-up issues: non-HEIC images started going through MIME sniffing unexpectedly, and OpenAI chat-completionsmaxTotalImageBytesstill counted pre-normalized HEIC base64 bytes instead of the larger post-conversion JPEG payload.detectMimemocking, and chat-completions total image budgeting now counts the normalized image payload.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
input_imageinputs keep their previous declared-MIME behavior.maxTotalImageBytesnow correctly applies after HEIC/HEIF normalization to JPEG.Security Impact (required)
Yes/No) NoYes/No) NoYes/No) NoYes/No) NoYes/No) NoYes, explain risk + mitigation:Repro + Verification
Environment
input_imagegateway.http.endpoints.chatCompletions.maxTotalImageBytesSteps
image_urldata URIs and a tightmaxTotalImageByteslimit.Expected
Actual
Evidence
Attach at least one:
Human Verification (required)
What you personally verified (not just CI), and how:
maxTotalImageBytes.Compatibility / Migration
Yes/No) YesYes/No) NoYes/No) NoFailure Recovery (if this breaks)
src/media/input-files.ts,src/gateway/openai-http.tsRisks and Mitigations