Context
Project icons (#67) are decoded synchronously in GroupHeaderRow.__init__, on the main thread, once per project per sidebar rebuild — including at app startup for every project in the session history, and immediately when a new session's project row is created.
The rendering path is already hardened (#67): bytes are vetted before parsing (gzip/svgz and non-XML content refused, 256 KB cap), the pixbuf loader is forced to the SVG codec so content sniffing can't reach other decoders, and rasterization is bounded to the icon size.
What remains
A valid SVG can still be expensive to parse/render: deep nesting, heavy filter chains (e.g. feTurbulence), pattern/use fan-out, entity expansion up to libxml2's built-in limits. A hostile repo could make the sidebar — and therefore the whole app — hang for seconds or worse just by existing in the session list, with no user interaction.
Not currently a practical problem (librsvg has internal element-count and cycle limits, and the size cap bounds input), so this is a tracking issue in case it ever shows up in the wild.
Possible mitigations, roughly in order of effort
- Decode off the main thread (thread +
GLib.idle_add, same pattern as the store's scan) and swap the texture in when ready; rows show the folder fallback in the meantime.
- Cache the rendered texture per (path, mtime, size) so the cost is paid once per icon change rather than per rebuild.
- Decode in a short-lived subprocess with a timeout for full isolation (probably over-engineering for a local desktop tool).
🤖 Generated with Claude Code
https://claude.ai/code/session_01NWcqNwkCLdwN4gExvhAAwC
Context
Project icons (#67) are decoded synchronously in
GroupHeaderRow.__init__, on the main thread, once per project per sidebar rebuild — including at app startup for every project in the session history, and immediately when a new session's project row is created.The rendering path is already hardened (#67): bytes are vetted before parsing (gzip/svgz and non-XML content refused, 256 KB cap), the pixbuf loader is forced to the SVG codec so content sniffing can't reach other decoders, and rasterization is bounded to the icon size.
What remains
A valid SVG can still be expensive to parse/render: deep nesting, heavy filter chains (e.g.
feTurbulence), pattern/use fan-out, entity expansion up to libxml2's built-in limits. A hostile repo could make the sidebar — and therefore the whole app — hang for seconds or worse just by existing in the session list, with no user interaction.Not currently a practical problem (librsvg has internal element-count and cycle limits, and the size cap bounds input), so this is a tracking issue in case it ever shows up in the wild.
Possible mitigations, roughly in order of effort
GLib.idle_add, same pattern as the store's scan) and swap the texture in when ready; rows show the folder fallback in the meantime.🤖 Generated with Claude Code
https://claude.ai/code/session_01NWcqNwkCLdwN4gExvhAAwC