-
Notifications
You must be signed in to change notification settings - Fork 7
Preview/React Doctor #106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Preview/React Doctor #106
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "name": "react-doctor-cr-test", | ||
| "private": true, | ||
| "type": "module", | ||
| "dependencies": { | ||
| "react": "^18.3.0", | ||
| "react-dom": "^18.3.0" | ||
| }, | ||
| "devDependencies": { | ||
| "typescript": "^5.0.0", | ||
| "@types/react": "^18.0.0", | ||
| "@types/react-dom": "^18.0.0" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,34 @@ | ||||||||||||||||
| import { createContext, useState } from "react"; | ||||||||||||||||
| import { AssertiveHints } from "./AssertiveHints.js"; | ||||||||||||||||
|
|
||||||||||||||||
| const items = ["alpha", "beta", "gamma"]; | ||||||||||||||||
|
|
||||||||||||||||
| export function App() { | ||||||||||||||||
| const ThemeContext = createContext("light"); | ||||||||||||||||
| const [userHtml] = useState("<img src=x onerror=alert(1)>"); | ||||||||||||||||
| const userInput = "alert('xss')"; | ||||||||||||||||
|
|
||||||||||||||||
| return ( | ||||||||||||||||
| <ThemeContext.Provider value="dark"> | ||||||||||||||||
| <main> | ||||||||||||||||
| <div dangerouslySetInnerHTML={{ __html: userHtml }} /> | ||||||||||||||||
| <a href="javascript:alert(1)">click me</a> | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -name "App.tsx" -type fRepository: coderabbitai/coderabbit-pr-review Length of output: 91 🏁 Script executed: cat -n ./src/App.tsxRepository: coderabbitai/coderabbit-pr-review Length of output: 1216 Replace
Suggested fix- <a href="javascript:alert(1)">click me</a>
+ <button type="button" onClick={() => window.alert("clicked")}>
+ click me
+ </button>📝 Committable suggestion
Suggested change
🧰 Tools🪛 React Doctor (0.5.6)[error] 15-15: A Use real event handlers instead of (jsx-no-script-url) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||
| <iframe src="https://example.com" title="embed" /> | ||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n src/App.tsx | head -30Repository: coderabbitai/coderabbit-pr-review Length of output: 1138 Sandbox the iframe by default. The embedded frame at line 16 currently has no sandbox restrictions. Add Suggested fix- <iframe src="https://example.com" title="embed" />
+ <iframe
+ src="https://example.com"
+ title="embed"
+ sandbox=""
+ referrerPolicy="no-referrer"
+ />📝 Committable suggestion
Suggested change
🧰 Tools🪛 React Doctor (0.5.6)[error] 16-16: An Add (iframe-missing-sandbox) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||
| <ul> | ||||||||||||||||
| {items.map((item) => ( | ||||||||||||||||
| <li>{item}</li> | ||||||||||||||||
| ))} | ||||||||||||||||
|
Comment on lines
+18
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -name "App.tsx" -type fRepository: coderabbitai/coderabbit-pr-review Length of output: 91 🏁 Script executed: head -30 src/App.tsx 2>/dev/null || head -30 App.tsx 2>/dev/null || echo "File not found in expected locations"Repository: coderabbitai/coderabbit-pr-review Length of output: 928 Add a stable The list items at lines 18-20 are missing keys. While this may not cause issues with the current static array, React requires keys to properly identify items when re-rendering, especially if the list order changes. Suggested fix {items.map((item) => (
- <li>{item}</li>
+ <li key={item}>{item}</li>
))}📝 Committable suggestion
Suggested change
🧰 Tools🪛 React Doctor (0.5.6)[error] 19-19: Your users can see the wrong data when this list reorders. Add a stable (jsx-key) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||
| </ul> | ||||||||||||||||
| <button | ||||||||||||||||
| onClick={() => { | ||||||||||||||||
| eval(userInput); | ||||||||||||||||
| new Function(userInput)(); | ||||||||||||||||
|
Comment on lines
+24
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n src/App.tsx | head -40Repository: coderabbitai/coderabbit-pr-review Length of output: 1216 Remove dynamic code execution ( Both statements execute arbitrary code from string input and create direct code-injection vulnerabilities. The Suggested fix <button
onClick={() => {
- eval(userInput);
- new Function(userInput)();
+ console.info("Received input", userInput);
}}
>📝 Committable suggestion
Suggested change
🧰 Tools🪛 React Doctor (0.5.6)[error] 24-24: eval() is a code-injection vulnerability: it runs any string as code. Use (no-eval) [error] 25-25: new Function() is a code-injection vulnerability: it builds & runs code from a string. Use (no-eval) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||
| }} | ||||||||||||||||
| > | ||||||||||||||||
| run | ||||||||||||||||
| </button> | ||||||||||||||||
| <AssertiveHints /> | ||||||||||||||||
| </main> | ||||||||||||||||
| </ThemeContext.Provider> | ||||||||||||||||
| ); | ||||||||||||||||
| } | ||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,21 @@ | ||||||||||||||||||||||
| type RowProps = { | ||||||||||||||||||||||
| label: string; | ||||||||||||||||||||||
| onSelect: () => void; | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| function Row({ label, onSelect }: RowProps) { | ||||||||||||||||||||||
| return <span>{label}</span>; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
Comment on lines
+6
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n src/AssertiveHints.tsxRepository: coderabbitai/coderabbit-pr-review Length of output: 680 Wire
Suggested fix function Row({ label, onSelect }: RowProps) {
- return <span>{label}</span>;
+ return (
+ <button type="button" onClick={onSelect}>
+ {label}
+ </button>
+ );
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| export function AssertiveHints() { | ||||||||||||||||||||||
| const handleAction = () => console.log("action"); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return ( | ||||||||||||||||||||||
| <section> | ||||||||||||||||||||||
| <button>Save</button> | ||||||||||||||||||||||
| <img src="/logo.png" /> | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n src/AssertiveHints.tsx | head -25Repository: coderabbitai/coderabbit-pr-review Length of output: 680 Add The image is missing an accessible text alternative. Suggested fix- <img src="/logo.png" />
+ <img src="/logo.png" alt="Logo" />📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| <div onClick={handleAction}>Open menu</div> | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Check if the file exists and examine the relevant section
cat -n src/AssertiveHints.tsx | head -30Repository: coderabbitai/coderabbit-pr-review Length of output: 680 Use an interactive element instead of a clickable
Suggested fix- <div onClick={handleAction}>Open menu</div>
+ <button type="button" onClick={handleAction}>
+ Open menu
+ </button>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| <Row label="item-a" onSelect={() => console.log("selected")} /> | ||||||||||||||||||||||
| </section> | ||||||||||||||||||||||
| ); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { createRoot } from "react-dom/client"; | ||
| import { App } from "./App.js"; | ||
|
|
||
| const root = document.getElementById("root"); | ||
| if (root) { | ||
| createRoot(root).render(<App />); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "target": "ES2020", | ||
| "lib": ["ES2020", "DOM", "DOM.Iterable"], | ||
| "jsx": "react-jsx", | ||
| "module": "ESNext", | ||
| "moduleResolution": "bundler", | ||
| "strict": true, | ||
| "noEmit": true, | ||
| "skipLibCheck": true, | ||
| "isolatedModules": true | ||
| }, | ||
| "include": ["src"] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 146
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 95
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 492
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 91
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 131
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 1216
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 350
🏁 Script executed:
Repository: coderabbitai/coderabbit-pr-review
Length of output: 127
Remove XSS vulnerability:
dangerouslySetInnerHTMLrenders unescaped user input.The
userHtmlvariable contains executable markup (<img src=x onerror=alert(1)>), which will be parsed and executed as HTML, triggering the XSS attack directly in the browser.Suggested fix
Replace with JSX interpolation to automatically escape HTML entities and prevent execution of embedded scripts.
📝 Committable suggestion
🧰 Tools
🪛 React Doctor (0.5.6)
[error] 14-14:
dangerouslySetInnerHTMLis 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
Source: Linters/SAST tools