Reject unsupported js_repl image MIME types#19292
Merged
etraut-openai merged 1 commit intomainfrom Apr 24, 2026
Merged
Conversation
bolinfest
approved these changes
Apr 24, 2026
Collaborator
bolinfest
left a comment
There was a problem hiding this comment.
I don't feel strongly about any of these comments, FYI!
| return mediaType; | ||
| } | ||
|
|
||
| function validateEmitImageMimeType(mimeType) { |
Collaborator
There was a problem hiding this comment.
I would consider naming assertEmitImageMimeType() to underscore the fact that this will throw.
I'm so used to Rust: should we return something Result-like instead of throwing? I'm not familiar with how we handle error-handling in this code.
| if (commaIndex < 0) { | ||
| throw new Error("codex.emitImage expected a valid image data URL"); | ||
| } | ||
| const mediaType = dataUrl.slice(5, commaIndex).split(";")[0]; |
Collaborator
There was a problem hiding this comment.
Is this where the 5 comes from?
Suggested change
| const mediaType = dataUrl.slice(5, commaIndex).split(";")[0]; | |
| const mediaType = dataUrl.slice('data:'.length, commaIndex).split(";")[0]; |
Comment on lines
+1263
to
+1272
| if ( | ||
| normalized !== "image/png" && | ||
| normalized !== "image/jpeg" && | ||
| normalized !== "image/webp" && | ||
| normalized !== "image/gif" | ||
| ) { | ||
| throw new Error( | ||
| "codex.emitImage only supports image/png, image/jpeg, image/webp, or image/gif", | ||
| ); | ||
| } |
Collaborator
There was a problem hiding this comment.
Alternative to the repeated !==?
Suggested change
| if ( | |
| normalized !== "image/png" && | |
| normalized !== "image/jpeg" && | |
| normalized !== "image/webp" && | |
| normalized !== "image/gif" | |
| ) { | |
| throw new Error( | |
| "codex.emitImage only supports image/png, image/jpeg, image/webp, or image/gif", | |
| ); | |
| } | |
| const SUPPORTED_IMAGE_TYPES = [ | |
| "image/png", | |
| "image/jpeg", | |
| "image/webp", | |
| "image/gif", | |
| ]; | |
| if (!SUPPORTED_IMAGE_TYPES.includes(normalized)) { | |
| throw new Error( | |
| `codex.emitImage only supports ${SUPPORTED_IMAGE_TYPES.join(", ")}`, | |
| ); | |
| } |
Comment on lines
+1801
to
+1806
| if !image_url | ||
| .get(..5) | ||
| .is_some_and(|scheme| scheme.eq_ignore_ascii_case("data:")) | ||
| { | ||
| return Err("codex.emitImage only accepts data URLs".to_string()); | ||
| } |
Collaborator
There was a problem hiding this comment.
strip_prefix() to the rescue!
Suggested change
| if !image_url | |
| .get(..5) | |
| .is_some_and(|scheme| scheme.eq_ignore_ascii_case("data:")) | |
| { | |
| return Err("codex.emitImage only accepts data URLs".to_string()); | |
| } | |
| let data_payload = image_url.strip_prefix("data:").ok_or_else(|| anyhow!("expected data: URI but got `{image_url}`"))?; |
Oh, but you need to support eq_ignore_ascii_case()? Is that a thing for URIs?
d75e908 to
871e02c
Compare
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Summary
codex.emitImageaccepted arbitrary image MIME types for byte payloads and data URLs. That allowed a value likeimage/rgbato be wrapped as aninput_image, even though it is not a supported encoded image format, so the invalid image could reach the model-input path and trigger output sanitization.This results in a panic in debug builds because the output sanitization is meant as a final safety net, not a primary means of rejecting invalid image types. I've hit this case multiple times when executing certain long-running tasks.
This PR rejects unsupported image MIME types before they are emitted from
js_repl.Changes
codex.emitImage({ bytes, mimeType })in the JS kernel so only encoded PNG, JPEG, WebP, or GIF payloads are accepted.