fix: updates log details view to show input images from user messages#2983
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR updates two UI components to extract image URLs from message Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
|
Confidence Score: 5/5Safe to merge; the one open finding is a minor hardening suggestion, not a blocking defect. All remaining findings are P2 style/hardening suggestions (adding No files require special attention beyond the optional
|
| Filename | Overview |
|---|---|
| ui/app/workspace/logs/sheets/logDetailView.tsx | Adds inline image rendering for image_url (chat) and input_image (Responses API) content blocks; logic is correct but images lack referrerPolicy="no-referrer" |
| ui/app/workspace/logs/views/logChatMessageView.tsx | Replaces JSON code-editor rendering of image_url blocks with an inline <img> tag; fallthrough when url is empty is safe (returns null at end of function) |
Reviews (3): Last reviewed commit: "fix: updates log details view to show in..." | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 1493-1507: The image rendering block is producing duplicate images
for image-only chat messages because LogChatMessageView already renders
image_url blocks; update the conditional around the
Array.isArray(message.content) ... .filter(...) rendering so it skips rendering
when the message is a chat message with no text (e.g., check message.text or
message.type === 'chat' and message.text?.trim() === ''), or otherwise only
render image_url blocks when LogChatMessageView is not responsible; reference
message.content, ContentBlock, and LogChatMessageView to locate and change the
logic so image-only messages don't render images twice.
- Around line 1500-1502: Replace the unstable index keys and guard undefined
URLs when rendering images: change the list item that currently uses key={i}
with key derived from the image URL (e.g., use key={src} where the variable src
is the image URL), and in the mapping over msg.content (the items named b with
b.type === "input_image") either filter out falsy b.image_url first
(msg.content.filter(b => b?.type === "input_image" && b.image_url).map(...)) or
add an in-map guard and skip rendering when b.image_url is missing; when
rendering use a stable key such as key={b.image_url} instead of the array index.
In `@ui/app/workspace/logs/views/logChatMessageView.tsx`:
- Around line 45-48: The code reads an untrusted image URL from
block.image_url.url into src and renders it directly in an <img>, which can leak
data or solicit unsafe schemes; validate and sanitize the URL before rendering
in logChatMessageView.tsx by constructing a URL object from block.image_url.url
and only allowing safe schemes (e.g., https and optionally http if you accept
it), optionally check against an allowlist of hosts, and reject anything else
(fall back to a placeholder or skip rendering); when rendering the <img>, set
safer attributes such as loading="lazy" and referrerPolicy="no-referrer" (and
avoid crossorigin unless explicitly needed) to reduce privacy exposure.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1ba98e9f-7433-47c7-8a9a-477cf052bec1
📒 Files selected for processing (2)
ui/app/workspace/logs/sheets/logDetailView.tsxui/app/workspace/logs/views/logChatMessageView.tsx
7793cb2 to
f5332b9
Compare
59e37e6 to
8836145
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
ui/app/workspace/logs/sheets/logDetailView.tsx (1)
1501-1503:⚠️ Potential issue | 🟡 MinorAvoid index-derived keys for image lists.
Line 1502 and Line 1619 still include the loop index in keys. Prefer stable content-based keys (
src/b.image_url) for these mapped image blocks.Suggested key update
- .map((b, i) => { + .map((b) => { const src = b.image_url?.url; if (!src) return null; return ( <img - key={`${i}-${src}`} + key={src} src={src} alt="Attached image" className="mt-2 max-w-full rounded border" /> ); }) ... - .map((b, i) => ( - <img key={`${i}-${b.image_url}`} src={b.image_url} alt="Attached image" className="mt-2 max-w-full rounded border" /> + .map((b) => ( + <img key={b.image_url} src={b.image_url} alt="Attached image" className="mt-2 max-w-full rounded border" /> ))As per coding guidelines: "Always use stable, unique keys in lists; never use array index as key unless unavoidable".
Also applies to: 1618-1619
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ui/app/workspace/logs/sheets/logDetailView.tsx` around lines 1501 - 1503, The mapped image elements in logDetailView (the <img> rendered with key={`${i}-${src}`} and the other using index + b.image_url) are using index-derived keys; change both to use stable unique content-based keys (e.g., use src as the key for the first image map and b.image_url for the second) so keys become something like key={src} / key={b.image_url} and remove the index portion to ensure stable reconciliation.ui/app/workspace/logs/views/logChatMessageView.tsx (1)
45-48:⚠️ Potential issue | 🟠 MajorHarden untrusted image URLs before rendering.
Line 45 feeds log data directly into
<img src>. This enables arbitrary external fetches from the operator browser. Gate allowed schemes and add safer image attributes.Suggested hardening
+const isSafeImageSrc = (value: string) => + /^(https?:\/\/|data:image\/|blob:)/i.test(value); + // Handle image content if (block.image_url) { const src = block.image_url.url; - if (src) { - return <img src={src} alt="Attached image" className="max-w-full rounded border" />; + if (src && isSafeImageSrc(src)) { + return ( + <img + src={src} + alt="Attached image" + loading="lazy" + referrerPolicy="no-referrer" + className="max-w-full rounded border" + /> + ); } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ui/app/workspace/logs/views/logChatMessageView.tsx` around lines 45 - 48, The image URL is used raw in the JSX (block.image_url.url in logChatMessageView.tsx) which can trigger unsafe external fetches; add a validation step (e.g., implement an isSafeImageUrl or sanitizeImageUrl helper) that parses the URL (new URL(...)) and only allows safe schemes (http, https, optionally data) and rejects javascript:, blob:, and other schemes, and if the URL is invalid or disallowed render a safe placeholder or nothing; when rendering the <img> include safer attributes such as referrerPolicy="no-referrer", loading="lazy", decoding="async" and crossOrigin="anonymous" to limit information leakage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 1493-1508: The image-rendering paths in logDetailView.tsx render
untrusted URLs directly into <img src> (see the inline branch that filters
message.content for type "image_url" and the other branch around lines
1615-1620); update both branches to run each image URL through the existing
safe-src sanitization utility (reuse the same guard used elsewhere in this
file), skip rendering if the sanitized URL is falsy, and add privacy-friendly
attributes to the <img> tag (e.g., referrerPolicy="no-referrer" and
decoding="async" or appropriate attributes used elsewhere) so that all
log-provided URLs are validated and rendered consistently across both code
paths.
---
Duplicate comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 1501-1503: The mapped image elements in logDetailView (the <img>
rendered with key={`${i}-${src}`} and the other using index + b.image_url) are
using index-derived keys; change both to use stable unique content-based keys
(e.g., use src as the key for the first image map and b.image_url for the
second) so keys become something like key={src} / key={b.image_url} and remove
the index portion to ensure stable reconciliation.
In `@ui/app/workspace/logs/views/logChatMessageView.tsx`:
- Around line 45-48: The image URL is used raw in the JSX (block.image_url.url
in logChatMessageView.tsx) which can trigger unsafe external fetches; add a
validation step (e.g., implement an isSafeImageUrl or sanitizeImageUrl helper)
that parses the URL (new URL(...)) and only allows safe schemes (http, https,
optionally data) and rejects javascript:, blob:, and other schemes, and if the
URL is invalid or disallowed render a safe placeholder or nothing; when
rendering the <img> include safer attributes such as
referrerPolicy="no-referrer", loading="lazy", decoding="async" and
crossOrigin="anonymous" to limit information leakage.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3bc0a110-e629-44ad-9bcd-756f39249197
📒 Files selected for processing (2)
ui/app/workspace/logs/sheets/logDetailView.tsxui/app/workspace/logs/views/logChatMessageView.tsx
Merge activity
|
f5332b9 to
ee59cfb
Compare
8836145 to
8752072
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (2)
ui/app/workspace/logs/sheets/logDetailView.tsx (1)
1493-1508:⚠️ Potential issue | 🟠 MajorApply safe-src validation consistently for both image-rendering branches.
At Line 1503 and Line 1619, URLs from logs are used directly in
<img src>. Reuse a safe-source guard and privacy attributes in both branches.Suggested fix
+const isSafeImageSrc = (value: string) => + /^(https?:\/\/|data:image\/|blob:)/i.test(value); {text && Array.isArray(message.content) && (message.content as ContentBlock[]) .filter((b) => b.type === "image_url") .map((b, i) => { const src = b.image_url?.url; - if (!src) return null; + if (!src || !isSafeImageSrc(src)) return null; return ( <img key={`${i}-${src}`} src={src} alt="Attached image" + loading="lazy" + referrerPolicy="no-referrer" className="mt-2 max-w-full rounded border" /> ); })} {Array.isArray(msg.content) && msg.content .filter((b) => b?.type === "input_image" && b.image_url) - .map((b, i) => ( - <img key={`${i}-${b.image_url}`} src={b.image_url} alt="Attached image" className="mt-2 max-w-full rounded border" /> - ))} + .map((b, i) => + isSafeImageSrc(b.image_url as string) ? ( + <img + key={`${i}-${b.image_url}`} + src={b.image_url} + alt="Attached image" + loading="lazy" + referrerPolicy="no-referrer" + className="mt-2 max-w-full rounded border" + /> + ) : null + )}Also applies to: 1615-1620
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ui/app/workspace/logs/sheets/logDetailView.tsx` around lines 1493 - 1508, The image branch using (message.content as ContentBlock[]).filter(... type === "image_url") currently injects raw URLs into <img src> without the same safe-source validation and privacy attributes used elsewhere; update this branch to run each b.image_url?.url through the existing safeSrc (or equivalent) guard before rendering and skip images that fail validation, and add the same privacy attributes (e.g., referrerPolicy="no-referrer", loading="lazy", and any other attrs used in the other branch) to the <img> element so both image-rendering paths use consistent validation and privacy protections (refer to message.content, ContentBlock, and image_url in logDetailView.tsx to locate the code).ui/app/workspace/logs/views/logChatMessageView.tsx (1)
45-48:⚠️ Potential issue | 🟠 MajorHarden image URL rendering before using it in
src.At Line 45 and Line 47, the URL is rendered directly from log data. Please gate to safe schemes and add privacy/perf-safe attributes.
Suggested fix
+const isSafeImageSrc = (value: string) => + /^(https?:\/\/|data:image\/|blob:)/i.test(value); // Handle image content if (block.image_url) { const src = block.image_url.url; - if (src) { - return <img src={src} alt="Attached image" className="max-w-full rounded border" />; + if (src && isSafeImageSrc(src)) { + return ( + <img + src={src} + alt="Attached image" + loading="lazy" + referrerPolicy="no-referrer" + className="max-w-full rounded border" + /> + ); } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ui/app/workspace/logs/views/logChatMessageView.tsx` around lines 45 - 48, In logChatMessageView.tsx, avoid rendering block.image_url.url directly into the img src; validate and sanitize the URL (e.g., using the URL constructor to parse block.image_url.url and only allow http: or https: schemes), and if invalid or unsafe, skip rendering or render a safe fallback; when rendering, add privacy/perf attributes such as loading="lazy" decoding="async" and rel="noreferrer noopener" (for linked images) and consider adding crossOrigin as appropriate to the <img> output to prevent leaking referrers and improve performance. Ensure these checks are performed at the place where src is assigned (reference block.image_url.url and the rendering branch in the component) so unsafe schemes are never passed to the img element.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@ui/app/workspace/logs/sheets/logDetailView.tsx`:
- Around line 1493-1508: The image branch using (message.content as
ContentBlock[]).filter(... type === "image_url") currently injects raw URLs into
<img src> without the same safe-source validation and privacy attributes used
elsewhere; update this branch to run each b.image_url?.url through the existing
safeSrc (or equivalent) guard before rendering and skip images that fail
validation, and add the same privacy attributes (e.g.,
referrerPolicy="no-referrer", loading="lazy", and any other attrs used in the
other branch) to the <img> element so both image-rendering paths use consistent
validation and privacy protections (refer to message.content, ContentBlock, and
image_url in logDetailView.tsx to locate the code).
In `@ui/app/workspace/logs/views/logChatMessageView.tsx`:
- Around line 45-48: In logChatMessageView.tsx, avoid rendering
block.image_url.url directly into the img src; validate and sanitize the URL
(e.g., using the URL constructor to parse block.image_url.url and only allow
http: or https: schemes), and if invalid or unsafe, skip rendering or render a
safe fallback; when rendering, add privacy/perf attributes such as
loading="lazy" decoding="async" and rel="noreferrer noopener" (for linked
images) and consider adding crossOrigin as appropriate to the <img> output to
prevent leaking referrers and improve performance. Ensure these checks are
performed at the place where src is assigned (reference block.image_url.url and
the rendering branch in the component) so unsafe schemes are never passed to the
img element.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c5511e16-799e-44a5-9862-b3b1a72fa50a
📒 Files selected for processing (2)
ui/app/workspace/logs/sheets/logDetailView.tsxui/app/workspace/logs/views/logChatMessageView.tsx
The base branch was changed.

Summary
Images attached to log messages were not being rendered visually in the log detail view. Instead, image content blocks were displayed as raw JSON in a collapsible code editor, making it difficult to inspect attached images at a glance.
Changes
image_urlcontent blocks inlogChatMessageView.tsxwith an inline<img>tag that renders the image directly.logDetailView.tsxforimage_url-type content blocks in chat messages andinput_image-type content blocks in Responses API messages.Type of change
Affected areas
How to test
image_urlorinput_imagecontent block).Screenshots/Recordings
Before: Image content blocks were shown as collapsed JSON in a code editor.
After: Images are rendered inline as
<img>elements with rounded borders.After screenshots:
Breaking changes
Related issues
Security considerations
Image sources are rendered directly from log data. Ensure that only trusted or sanitized URLs are stored in log entries to avoid rendering arbitrary external content.
Checklist
docs/contributing/README.mdand followed the guidelines