Skip to content

upgrade to svelte 5.x#435

Open
hchen2020 wants to merge 1 commit intoSciSharp:mainfrom
hchen2020:svelte-5.x
Open

upgrade to svelte 5.x#435
hchen2020 wants to merge 1 commit intoSciSharp:mainfrom
hchen2020:svelte-5.x

Conversation

@hchen2020
Copy link
Contributor

@hchen2020 hchen2020 commented Mar 20, 2026

This PR upgrade Svelte from 4.x to 5.x

@qodo-code-review
Copy link

Review Summary by Qodo

Upgrade to Svelte 5.x with tag syntax fixes and dependency updates

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Upgrade Svelte from v4 to v5 with updated dependencies
• Convert self-closing HTML tags to explicit closing tags for Svelte 5 compatibility
• Update SCSS imports to use node_modules alias resolution
• Add dynamic color override support via environment variables
• Redesign home page with new layout and environment switcher
Diagram
flowchart LR
  A["Svelte 4.x"] -->|"Upgrade"| B["Svelte 5.x"]
  B -->|"Update Dependencies"| C["@sveltejs/kit 2.55.0<br/>@sveltestrap 7.1.0<br/>vite 6.4.1"]
  D["Self-closing Tags<br/>e.g. &lt;i /&gt;"] -->|"Convert to"| E["Explicit Closing Tags<br/>e.g. &lt;i&gt;&lt;/i&gt;"]
  F["SCSS Imports"] -->|"Simplify"| G["Use node_modules alias"]
  H["Home Page"] -->|"Redesign"| I["New Layout + Env Switcher"]
  J["Color Config"] -->|"Add"| K["PUBLIC_PRIMARY_COLOR<br/>PUBLIC_SECONDARY_COLOR"]
Loading

Grey Divider

File Changes

1. src/routes/chat/[agentId]/[conversationId]/chat-box.svelte ✨ Enhancement +23/-27

Convert self-closing icon tags to explicit closing tags

src/routes/chat/[agentId]/[conversationId]/chat-box.svelte


2. src/routes/(home)/+page.svelte ✨ Enhancement +103/-47

Redesign home page with new layout and environment switcher

src/routes/(home)/+page.svelte


3. src/routes/page/knowledge-base/documents/+page.svelte ✨ Enhancement +11/-11

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/documents/+page.svelte


View more (80)
4. src/routes/page/knowledge-base/FileLeftBar.svelte ✨ Enhancement +9/-12

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/FileLeftBar.svelte


5. src/routes/page/knowledge-base/question-answer/+page.svelte ✨ Enhancement +10/-10

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/question-answer/+page.svelte


6. src/routes/page/agent/card-agent.svelte ✨ Enhancement +5/-5

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/card-agent.svelte


7. src/lib/common/audio-player/AudioPlayer.svelte ✨ Enhancement +3/-5

Convert self-closing div tags to explicit closing tags

src/lib/common/audio-player/AudioPlayer.svelte


8. src/routes/page/dashboard/+page.svelte ✨ Enhancement +6/-6

Convert self-closing icon tags to explicit closing tags

src/routes/page/dashboard/+page.svelte


9. src/lib/common/shared/PlainPagination.svelte ✨ Enhancement +4/-4

Convert self-closing icon tags to explicit closing tags

src/lib/common/shared/PlainPagination.svelte


10. src/lib/common/dropdowns/NotificationDropdown.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/lib/common/dropdowns/NotificationDropdown.svelte


11. src/routes/page/dashboard/SocialSource.svelte ✨ Enhancement +5/-5

Convert self-closing icon tags to explicit closing tags

src/routes/page/dashboard/SocialSource.svelte


12. src/lib/common/dropdowns/ProfileDropdown.svelte ✨ Enhancement +4/-4

Convert self-closing icon tags to explicit closing tags

src/lib/common/dropdowns/ProfileDropdown.svelte


13. src/routes/(authentication)/register/+page.svelte ✨ Enhancement +4/-4

Convert self-closing icon tags to explicit closing tags

src/routes/(authentication)/register/+page.svelte


14. src/routes/chat/[agentId]/[conversationId]/persist-log/persist-log.svelte ✨ Enhancement +4/-4

Convert self-closing icon tags to explicit closing tags

src/routes/chat/[agentId]/[conversationId]/persist-log/persist-log.svelte


15. src/routes/page/conversation/+page.svelte ✨ Enhancement +6/-6

Convert self-closing icon tags to explicit closing tags

src/routes/page/conversation/+page.svelte


16. src/routes/page/knowledge-base/Storage.svelte ✨ Enhancement +6/-6

Convert self-closing icon and div tags to explicit closing tags

src/routes/page/knowledge-base/Storage.svelte


17. src/routes/page/agent/+page.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/+page.svelte


18. src/routes/VerticalLayout/Sidebar.svelte ✨ Enhancement +2/-2

Convert self-closing icon tags to explicit closing tags

src/routes/VerticalLayout/Sidebar.svelte


19. src/routes/+layout.svelte ✨ Enhancement +29/-0

Add dynamic color override support via environment variables

src/routes/+layout.svelte


20. src/lib/common/dropdowns/Select.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/lib/common/dropdowns/Select.svelte


21. src/routes/page/agent/[agentId]/agent-components/utilities/agent-utility-item.svelte ✨ Enhancement +2/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/utilities/agent-utility-item.svelte


22. src/routes/page/knowledge-base/FileLists.svelte ✨ Enhancement +4/-4

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/FileLists.svelte


23. src/routes/page/agent/[agentId]/agent-components/rules/agent-rule.svelte ✨ Enhancement +2/-2

Convert self-closing icon and iframe tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/rules/agent-rule.svelte


24. src/lib/common/files/FileGallery.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/lib/common/files/FileGallery.svelte


25. src/lib/common/shared/RightSidebar.svelte ✨ Enhancement +2/-2

Convert self-closing icon and div tags to explicit closing tags

src/lib/common/shared/RightSidebar.svelte


26. src/routes/page/conversation/[conversationId]/conv-dialogs.svelte ✨ Enhancement +4/-5

Convert self-closing icon and textarea tags to explicit closing tags

src/routes/page/conversation/[conversationId]/conv-dialogs.svelte


27. src/routes/page/agent/[agentId]/agent-components/utilities/agent-utility.svelte ✨ Enhancement +2/-2

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/utilities/agent-utility.svelte


28. src/routes/page/knowledge-base/documents/knowledge-document-upload.svelte ✨ Enhancement +4/-4

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/documents/knowledge-document-upload.svelte


29. src/routes/page/plugin/plugin-list.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/plugin/plugin-list.svelte


30. src/routes/page/task/+page.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/task/+page.svelte


31. src/routes/page/knowledge-base/common/search/advanced-search.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/common/search/advanced-search.svelte


32. src/routes/VerticalLayout/Header.svelte ✨ Enhancement +2/-2

Convert self-closing icon and span tags to explicit closing tags

src/routes/VerticalLayout/Header.svelte


33. src/routes/page/task/task-item.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/task/task-item.svelte


34. src/routes/page/knowledge-base/dictionary/+page.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/dictionary/+page.svelte


35. src/lib/common/markdown/CodeBlock.svelte ✨ Enhancement +2/-2

Convert self-closing icon tags to explicit closing tags

src/lib/common/markdown/CodeBlock.svelte


36. src/routes/page/knowledge-base/common/vector-table/vector-item.svelte ✨ Enhancement +4/-4

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/common/vector-table/vector-item.svelte


37. src/lib/common/spinners/LoadingDots.svelte ✨ Enhancement +1/-2

Convert self-closing div tags to explicit closing tags

src/lib/common/spinners/LoadingDots.svelte


38. src/lib/common/shared/Stretch.svelte ✨ Enhancement +1/-2

Convert self-closing div tags to explicit closing tags

src/lib/common/shared/Stretch.svelte


39. src/lib/common/errors/error-500.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/lib/common/errors/error-500.svelte


40. src/routes/chat/[agentId]/[conversationId]/rich-content/rc-plain-options.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/chat/[agentId]/[conversationId]/rich-content/rc-plain-options.svelte


41. src/routes/page/agent/[agentId]/agent-components/mcp-tools/agent-mcp-tool.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/mcp-tools/agent-mcp-tool.svelte


42. src/lib/common/dropdowns/FullScreenDropdown.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/lib/common/dropdowns/FullScreenDropdown.svelte


43. src/routes/page/instruction/log/+page.svelte ✨ Enhancement +3/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/instruction/log/+page.svelte


44. src/routes/(authentication)/recoverpw/+page.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/(authentication)/recoverpw/+page.svelte


45. src/routes/page/agent/[agentId]/agent-components/knowledge-bases/agent-knowledge-base.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/knowledge-bases/agent-knowledge-base.svelte


46. src/routes/page/agent/[agentId]/agent-components/agent-template.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/agent-template.svelte


47. src/routes/page/agent/[agentId]/agent-components/rules/agent-rule-item.svelte ✨ Enhancement +1/-2

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/rules/agent-rule-item.svelte


48. src/routes/chat/+page.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/chat/+page.svelte


49. src/routes/page/agent/[agentId]/agent-components/agent-overview.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/agent-overview.svelte


50. src/lib/common/shared/LiveChatEntry.svelte ✨ Enhancement +1/-2

Convert self-closing iframe tags to explicit closing tags

src/lib/common/shared/LiveChatEntry.svelte


51. src/routes/page/instruction/testing/+page.svelte ✨ Enhancement +2/-3

Convert self-closing icon and textarea tags to explicit closing tags

src/routes/page/instruction/testing/+page.svelte


52. src/lib/common/audio-player/MessageAudioPlayer.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/lib/common/audio-player/MessageAudioPlayer.svelte


53. src/routes/page/agent/code-scripts/script-editor.svelte ✨ Enhancement +2/-2

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/code-scripts/script-editor.svelte


54. src/routes/page/knowledge-base/documents/knowledge-upload-result.svelte ✨ Enhancement +2/-2

Convert self-closing icon tags to explicit closing tags

src/routes/page/knowledge-base/documents/knowledge-upload-result.svelte


55. src/routes/(authentication)/login/+page.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/(authentication)/login/+page.svelte


56. src/lib/common/audio-player/AudioSpeaker.svelte ✨ Enhancement +1/-2

Convert self-closing icon tags to explicit closing tags

src/lib/common/audio-player/AudioSpeaker.svelte


57. src/routes/page/agent/[agentId]/agent-components/agent-instruction.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/agent-instruction.svelte


58. src/routes/page/setting/+page.svelte ✨ Enhancement +2/-2

Convert self-closing icon tags to explicit closing tags

src/routes/page/setting/+page.svelte


59. src/routes/page/agent/[agentId]/agent-components/knowledge-bases/agent-knowledge-base-item.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/knowledge-bases/agent-knowledge-base-item.svelte


60. src/routes/page/knowledge-base/common/vector-table/vector-item-edit-modal.svelte ✨ Enhancement +2/-4

Convert self-closing textarea tags to explicit closing tags

src/routes/page/knowledge-base/common/vector-table/vector-item-edit-modal.svelte


61. src/routes/page/agent/[agentId]/agent-components/mcp-tools/agent-mcp-tool-item.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/page/agent/[agentId]/agent-components/mcp-tools/agent-mcp-tool-item.svelte


62. src/lib/common/modals/DialogModal.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/lib/common/modals/DialogModal.svelte


63. src/lib/common/shared/BubbleChat.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/lib/common/shared/BubbleChat.svelte


64. src/routes/chat/[agentId]/[conversationId]/chat-util/chat-file-uploader.svelte ✨ Enhancement +1/-2

Convert self-closing icon tags to explicit closing tags

src/routes/chat/[agentId]/[conversationId]/chat-util/chat-file-uploader.svelte


65. src/lib/common/files/FileDropZone.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/lib/common/files/FileDropZone.svelte


66. src/routes/page/dashboard/Conversation.svelte ✨ Enhancement +2/-3

Convert self-closing icon tags to explicit closing tags

src/routes/page/dashboard/Conversation.svelte


67. src/routes/page/roles/role-item.svelte ✨ Enhancement +2/-2

Convert self-closing icon tags to explicit closing tags

src/routes/page/roles/role-item.svelte


68. src/routes/page/users/user-item.svelte ✨ Enhancement +2/-2

Convert self-closing icon tags to explicit closing tags

src/routes/page/users/user-item.svelte


69. src/routes/page/agent/[agentId]/build/components/CustomAnchor.svelte ✨ Enhancement +1/-1

Convert self-closing div tags to explicit closing tags

src/routes/page/agent/[agentId]/build/components/CustomAnchor.svelte


70. src/routes/page/dashboard/TopSellingProduct.svelte ✨ Enhancement +1/-1

Convert self-closing icon tags to explicit closing tags

src/routes/page/dashboard/TopSellingProduct.svelte


71. src/routes/page/knowledge-base/common/table/ 📦 Other +0/-0

src/routes/page/knowledge-base/common/table/


72. .env Additional files +4/-1

...

.env


73. package.json Additional files +14/-14

...

package.json


74. src/lib/scss/_variables.scss Additional files +2/-2

...

src/lib/scss/_variables.scss


75. src/lib/scss/app.scss Additional files +3/-3

...

src/lib/scss/app.scss


76. src/lib/scss/bootstrap.scss Additional files +3/-3

...

src/lib/scss/bootstrap.scss


77. src/routes/page/dashboard/RadialBarChart.svelte Additional files +1/-1

...

src/routes/page/dashboard/RadialBarChart.svelte


78. src/routes/page/dashboard/StackedColumnChart.svelte Additional files +1/-1

...

src/routes/page/dashboard/StackedColumnChart.svelte


79. src/routes/page/instruction/log/log-item.svelte Additional files +1/-1

...

src/routes/page/instruction/log/log-item.svelte


80. src/routes/page/knowledge-base/common/table/table-item.svelte Additional files +2/-2

...

src/routes/page/knowledge-base/common/table/table-item.svelte


81. src/routes/page/knowledge-base/documents/knowledge-upload-modal.svelte Additional files +1/-1

...

src/routes/page/knowledge-base/documents/knowledge-upload-modal.svelte


82. src/routes/page/users/+page.svelte Additional files +1/-1

...

src/routes/page/users/+page.svelte


83. vite.config.js Additional files +8/-0

...

vite.config.js


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Mar 20, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Action required

1. Env XSS via {@html} 🐞 Bug ⛨ Security
Description
src/routes/+layout.svelte injects a <style> tag using {@html} built from
PUBLIC_PRIMARY_COLOR / PUBLIC_SECONDARY_COLOR, so any value containing </style> can break out
and inject arbitrary HTML/JS. This is an app-wide XSS sink because it runs in the root layout head
for every page.
Code

src/routes/+layout.svelte[R36-40]

+<svelte:head>
+	{#if styleOverride}
+		{@html `<style>:root { ${styleOverride} }</style>`}
+	{/if}
+</svelte:head>
Evidence
The layout constructs styleOverride directly from public env vars and injects it as raw HTML into
<svelte:head>, which means the env var contents are not HTML-escaped before being interpreted by
the browser.

src/routes/+layout.svelte[16-40]
.env[25-27]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`src/routes/+layout.svelte` uses `{@html}` to inject a `&lt;style&gt;` element whose contents are built from `PUBLIC_PRIMARY_COLOR` / `PUBLIC_SECONDARY_COLOR`. Because `{@html}` bypasses escaping, a malformed or compromised env value containing `&lt;/style&gt;` can inject arbitrary HTML/JS.

## Issue Context
This runs in the root layout and affects every route.

## Fix
Avoid `{@html}` here. Prefer one of:
1) Set CSS variables via DOM APIs (safe from HTML injection):
- `onMount(() =&gt; document.documentElement.style.setProperty(&#x27;--bs-primary&#x27;, value))`
- and only set `--bs-*-rgb` after strict validation.

2) If you must emit a `&lt;style&gt;` tag, do it without `{@html}`:
- `&lt;svelte:head&gt;&lt;style&gt;{cssString}&lt;/style&gt;&lt;/svelte:head&gt;`
This prevents breaking out of the style element into HTML.

Also add strict validation (see next finding).

## Fix Focus Areas
- src/routes/+layout.svelte[16-40]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Invalid hex breaks rgb vars 🐞 Bug ✓ Correctness
Description
hexToRgb() accepts arbitrary strings and will emit invalid CSS (e.g., NaN, NaN, NaN) when a
provided color is not a strict 6-digit hex, which can break Bootstrap color rendering when overrides
are enabled. This affects the generated --bs-primary-rgb / --bs-secondary-rgb variables used
throughout the theme.
Code

src/routes/+layout.svelte[R16-33]

+	/** @type {Record<string, string>} */
+	const colorOverrides = {
+		...(PUBLIC_PRIMARY_COLOR   ? { '--bs-primary': PUBLIC_PRIMARY_COLOR, '--bs-primary-rgb': hexToRgb(PUBLIC_PRIMARY_COLOR) } : {}),
+		...(PUBLIC_SECONDARY_COLOR ? { '--bs-secondary': PUBLIC_SECONDARY_COLOR, '--bs-secondary-rgb': hexToRgb(PUBLIC_SECONDARY_COLOR) } : {}),
+	};
+
+	const styleOverride = Object.entries(colorOverrides).map(([k, v]) => `${k}:${v}`).join(';');
+
+	/**
+	 * Convert a hex color string to an "r, g, b" string for Bootstrap's rgb variables.
+	 * @param {string} hex
+	 * @returns {string}
+	 */
+	function hexToRgb(hex) {
+		const h = hex.replace('#', '');
+		const n = parseInt(h, 16);
+		return `${(n >> 16) & 255}, ${(n >> 8) & 255}, ${n & 255}`;
+	}
Evidence
hexToRgb() uses parseInt() without validating the input, and its output is always applied when a
corresponding env var is truthy; invalid input therefore produces invalid CSS variable values.

src/routes/+layout.svelte[16-33]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`hexToRgb()` does not validate that the input is a strict hex color. If `PUBLIC_PRIMARY_COLOR`/`PUBLIC_SECONDARY_COLOR` are set to a non-hex value (or a shorthand like `#fff`), `parseInt()` can produce `NaN` or unintended values, and the computed `--bs-*-rgb` variables become invalid.

## Issue Context
Bootstrap uses `--bs-*-rgb` in many `rgba()` usages; invalid rgb values can break colors across the UI.

## Fix
- Add a strict validator for `#RRGGBB` (optionally support `#RGB` by expanding it).
- If invalid, skip setting both the hex and rgb overrides for that color (or fall back to existing CSS vars).

Example logic:
- Normalize `hex` to `#RRGGBB`
- Validate with `/^#[0-9a-fA-F]{6}$/`
- Only then compute rgb.

## Fix Focus Areas
- src/routes/+layout.svelte[16-33]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Uncaught JSON.parse crash 🐞 Bug ⛯ Reliability
Description
src/routes/(home)/+page.svelte calls JSON.parse(PUBLIC_ENVIRONMENTS) during module
initialization without error handling, so any non-empty invalid JSON value will throw and prevent
the home route from rendering. This turns a configuration typo into a hard runtime/SSR failure.
Code

src/routes/(home)/+page.svelte[R20-22]

+    /** @type {{ label: string, url: string }[]} */
+    const environments = PUBLIC_ENVIRONMENTS ? JSON.parse(PUBLIC_ENVIRONMENTS) : [];
+
Evidence
The code performs JSON.parse directly on the env string with no try/catch or schema validation, so
invalid JSON deterministically throws a SyntaxError and aborts component initialization.

src/routes/(home)/+page.svelte[20-46]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The home page parses `PUBLIC_ENVIRONMENTS` using `JSON.parse()` without guarding against invalid JSON. If the env var is set to a non-empty invalid JSON string, initialization throws and the route fails to render.

## Issue Context
This code runs at component initialization (including SSR), so the failure is immediate and user-visible.

## Fix
- Wrap parsing in try/catch.
- Default to `[]` on failure.
- Optionally validate the parsed value is an array of `{label, url}` strings before rendering.

## Fix Focus Areas
- src/routes/(home)/+page.svelte[20-46]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@Oceania2018 Oceania2018 requested a review from iceljc March 20, 2026 16:10
Comment on lines +36 to +40
<svelte:head>
{#if styleOverride}
{@html `<style>:root { ${styleOverride} }</style>`}
{/if}
</svelte:head>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Env xss via {@html} 🐞 Bug ⛨ Security

src/routes/+layout.svelte injects a <style> tag using {@html} built from
PUBLIC_PRIMARY_COLOR / PUBLIC_SECONDARY_COLOR, so any value containing </style> can break out
and inject arbitrary HTML/JS. This is an app-wide XSS sink because it runs in the root layout head
for every page.
Agent Prompt
## Issue description
`src/routes/+layout.svelte` uses `{@html}` to inject a `<style>` element whose contents are built from `PUBLIC_PRIMARY_COLOR` / `PUBLIC_SECONDARY_COLOR`. Because `{@html}` bypasses escaping, a malformed or compromised env value containing `</style>` can inject arbitrary HTML/JS.

## Issue Context
This runs in the root layout and affects every route.

## Fix
Avoid `{@html}` here. Prefer one of:
1) Set CSS variables via DOM APIs (safe from HTML injection):
- `onMount(() => document.documentElement.style.setProperty('--bs-primary', value))`
- and only set `--bs-*-rgb` after strict validation.

2) If you must emit a `<style>` tag, do it without `{@html}`:
- `<svelte:head><style>{cssString}</style></svelte:head>`
This prevents breaking out of the style element into HTML.

Also add strict validation (see next finding).

## Fix Focus Areas
- src/routes/+layout.svelte[16-40]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant