[POC] Display viz images - #185
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces interactive MCP Apps (get-image and perform-analysis) along with supporting tools and endpoints to dynamically render images and stream analytical session updates. Key feedback includes addressing a DOM-based XSS vulnerability when rendering markdown, ensuring loading placeholders are cleaned up on image fetch failures, passing the metrics recorder to callGetImage for consistent telemetry, and restoring commented-out metrics flushing to prevent potential memory leaks.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const textEl = document.getElementById('ts-text'); | ||
| textEl.innerHTML = marked.parse(textContent); |
There was a problem hiding this comment.
Using innerHTML with marked.parse directly exposes the application to DOM-based Cross-Site Scripting (XSS) if the conversation content contains malicious HTML or markdown. To mitigate this, please sanitize the parsed HTML using a library like DOMPurify before setting innerHTML.
Ensure you also include the DOMPurify script in the HTML, for example: <script src='https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js'></script>
| const textEl = document.getElementById('ts-text'); | |
| textEl.innerHTML = marked.parse(textContent); | |
| const textEl = document.getElementById('ts-text'); | |
| textEl.innerHTML = DOMPurify.sanitize(marked.parse(textContent)); |
| }) | ||
| .catch((err) => { | ||
| console.error('>>> get image error', err); | ||
| }) |
There was a problem hiding this comment.
If the get_image tool call fails, the catch block is triggered, but the loading placeholder (newLoadingImg) is never removed from the DOM. This leaves a broken loading indicator permanently visible in the carousel.
Ensure that the loading element is cleaned up on failure as well.
| }) | |
| .catch((err) => { | |
| console.error('>>> get image error', err); | |
| }) | |
| }) | |
| .catch((err) => { | |
| console.error('>>> get image error', err); | |
| if (imagesContainer.contains(newLoadingImg)) { | |
| imagesContainer.removeChild(newLoadingImg); | |
| } | |
| updateCarouselState(); | |
| }) |
| case ToolName.GetImage: { | ||
| return this.callGetImage(request); | ||
| } |
There was a problem hiding this comment.
The recorder is not passed to callGetImage(request) in the switch case, which prevents the upstream getVizImage call from being tracked under the active request's metrics recorder.
Pass the recorder parameter to callGetImage to ensure consistent telemetry.
| case ToolName.GetImage: { | |
| return this.callGetImage(request); | |
| } | |
| case ToolName.GetImage: { | |
| return this.callGetImage(request, recorder); | |
| } |
| // scheduleRequestMetricsFlush(recorder, ctx); | ||
| // clearMetricsRecorderFromExecutionContext(ctx); |
There was a problem hiding this comment.
Commenting out scheduleRequestMetricsFlush and clearMetricsRecorderFromExecutionContext disables request metrics flushing and can lead to context/memory leaks in production. If this was done temporarily for the POC, please ensure it is restored before merging.
| // scheduleRequestMetricsFlush(recorder, ctx); | |
| // clearMetricsRecorderFromExecutionContext(ctx); | |
| scheduleRequestMetricsFlush(recorder, ctx); | |
| clearMetricsRecorderFromExecutionContext(ctx); |
No description provided.