Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions src/app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,15 @@ export default async function RootLayout({
className={isDark ? "dark" : ""}
suppressHydrationWarning
>
<head>
<script
nonce={nonce}
<head />
<body>
<div
suppressHydrationWarning
style={{ display: "none" }}
dangerouslySetInnerHTML={{
__html: `(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();`,
__html: `<script nonce="${nonce}">(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();</script>`,
Comment on lines +54 to +58

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Avoid emitting nonce="undefined" here.

nonce is optional in this layout, but string interpolation always writes an attribute. If x-nonce is ever missing, this becomes nonce="undefined" and the bootstrap script no longer satisfies CSP. Render a real <script> node and pass nonce={nonce} so the attribute is omitted when absent.

Suggested fix
-        <div
-          suppressHydrationWarning
-          style={{ display: "none" }}
-          dangerouslySetInnerHTML={{
-            __html: `<script nonce="${nonce}">(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();</script>`,
-          }}
-        />
+        <script
+          nonce={nonce}
+          suppressHydrationWarning
+          dangerouslySetInnerHTML={{
+            __html:
+              "(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();",
+          }}
+        />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
suppressHydrationWarning
style={{ display: "none" }}
dangerouslySetInnerHTML={{
__html: `(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();`,
__html: `<script nonce="${nonce}">(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();</script>`,
<script
nonce={nonce}
suppressHydrationWarning
dangerouslySetInnerHTML={{
__html:
"(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();",
}}
/>
🧰 Tools
🪛 ast-grep (0.44.0)

[warning] 56-56: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation

(react-unsafe-html-injection)

🪛 React Doctor (0.5.8)

[error] 57-57: dangerouslySetInnerHTML is an XSS hole that runs attacker-controlled HTML in your users' browsers.

Render trusted content as React children so attacker-controlled HTML cannot run in users' browsers.

(no-danger)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`[lang]/layout.tsx around lines 54 - 58, The layout’s inline theme
bootstrap is currently string-interpolating nonce into raw HTML, which can emit
nonce="undefined" when the value is missing. Update the logic in the layout
component that builds the bootstrap script so it renders an actual script
element and passes nonce={nonce} directly, ensuring the attribute is omitted
when absent and keeping CSP behavior correct.

}}
/>
</head>
<body>
<div className="grid-bg" aria-hidden="true" />
<Header
lang={lang}
Expand Down
10 changes: 10 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,13 @@ html.dark .react-flow__node.selected {
border-color: var(--color-brand-dark) !important;
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.4) !important;
}

/* Force code-related blocks to stay Left-to-Right in all locales */
pre,
code,
textarea.font-mono,
.font-mono textarea {
direction: ltr !important;
unicode-bidi: plaintext !important;
text-align: left !important;
}
2 changes: 1 addition & 1 deletion src/components/ui/CodeWorkspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ export default function CodeWorkspace({

{/* Body */}
{mode === "snippet" ? (
<div className="relative flex flex-1 overflow-hidden font-mono text-[13px] leading-[1.7]">
<div dir="ltr" className="relative flex flex-1 overflow-hidden font-mono text-[13px] leading-[1.7]">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

This only fixes snippet mode; project file paths still render under RTL.

The uploaded path list below (f.path at Lines 483-490) is still outside any dir="ltr" container, and the new globals.css rule does not cover those monospace list items. Arabic locale users can still see reordered / and [] there. Please extend the LTR wrapper or add a dedicated LTR container for the project-mode file list too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/CodeWorkspace.tsx` at line 425, The current LTR fix in
CodeWorkspace only covers snippet mode, while the project-mode uploaded path
list still renders under RTL. Update CodeWorkspace so the file list around the
f.path rendering is wrapped in an LTR container like the existing snippet view,
or otherwise ensure those monospace path items inherit dir="ltr". Keep the fix
targeted to the project file list elements and verify the relevant JSX block in
CodeWorkspace uses the same LTR handling for both modes.

<div
ref={gutterRef}
aria-hidden="true"
Expand Down
Loading