fix(visu): prevent stored XSS via SVG icon rendering#45
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a571bd191c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const svgContent = await getSvg(svgIconName(props.icon)) | ||
| if (!svgContent) return | ||
|
|
||
| const blob = new Blob([svgContent], { type: 'image/svg+xml' }) | ||
| svgBlobUrl.value = URL.createObjectURL(blob) |
There was a problem hiding this comment.
Prevent leaked blob URLs from stale async icon loads
load() creates a blob URL after await getSvg(...) without verifying that the request is still current. If icon changes rapidly (or the component unmounts) while an earlier load() is in flight, that stale call can still assign a new URL, and the previously created URL is never revoked because resetBlobUrl() only revokes the current value. This introduces a real memory leak path that did not exist with plain string rendering; add a request/version guard (or cancellation) and revoke URLs from discarded/stale loads.
Useful? React with 👍 / 👎.
| async function load() { | ||
| resetBlobUrl() | ||
| if (!isSvg.value) return | ||
|
|
||
| const svgContent = await getSvg(svgIconName(props.icon)) | ||
| if (!svgContent) return | ||
|
|
||
| const blob = new Blob([svgContent], { type: 'image/svg+xml' }) | ||
| svgBlobUrl.value = URL.createObjectURL(blob) |
There was a problem hiding this comment.
Ignore outdated SVG fetch results before assigning src
Because load() is async and updates svgBlobUrl unconditionally after await getSvg(...), a slower earlier request can overwrite a newer icon state. In practice, quickly switching icon (e.g. svg:a → svg:b or svg:a → emoji) can render the wrong SVG until another update occurs, since there is no token/check that the resolved content still matches the latest prop value.
Useful? React with 👍 / 👎.
Motivation
v-htmlin the visu icon component while preserving existing icon UX.Description
v-html) infrontend/src/components/VisuIcon.vuewith image rendering using a Blob URL created from the fetched SVG bytes.URL.revokeObjectURLto avoid leaking object URLs.<img>and addedloading="lazy"anddecoding="async"for efficient rendering.Testing
cd frontend && npm run typecheckand it completed without errors.Codex Task