Conversation
konamgil
commented
Mar 3, 2026
- fix(ssr): use escapeHtmlText (not escapeHtmlAttr) for <title> content so quote characters render correctly in browser tab ([Bug] title 태그 이중 주입 및 escapeHtmlAttr 오용으로 인한 잘못된 문자 인코딩 #112)
- fix(streaming-ssr): add WeakSet to isJSONSerializable to prevent infinite recursion on circular reference objects ([Bug] isJSONSerializable 순환 참조 미감지로 인한 서버 크래시 가능 #113)
- fix(bundler): fix XSS in dev error overlay — replace innerHTML with safe DOM textContent APIs (security: Dev error overlay vulnerable to XSS via unsanitized error messages #118)
- fix(css): filter Tailwind CLI progress messages from stderr so they are logged as info, not errors (bug: Tailwind CLI stderr progress messages incorrectly treated as errors #124)
- fix(dev): show HMR WebSocket port in port-conflict warning (bug: Port conflict warning is misleading — HMR port assignment not reported #116)
- fix(template): add dev:safe script to match lockfile warning message (bug: dev:safe script referenced in lockfile warning but missing from template package.json #128)
- fix(demo): add .gitignore to ai-chat, todo-list-mandu, island-first, ate-integration-test demos to prevent node_modules commit (mandu-chat-demo: .gitignore에 node_modules 누락 → file: 링크 사용 시 git pull/상태가 깨짐 #107)
- fix(ssr): use escapeHtmlText (not escapeHtmlAttr) for <title> content so quote characters render correctly in browser tab (#112) - fix(streaming-ssr): add WeakSet to isJSONSerializable to prevent infinite recursion on circular reference objects (#113) - fix(bundler): fix XSS in dev error overlay — replace innerHTML with safe DOM textContent APIs (#118) - fix(css): filter Tailwind CLI progress messages from stderr so they are logged as info, not errors (#124) - fix(dev): show HMR WebSocket port in port-conflict warning (#116) - fix(template): add dev:safe script to match lockfile warning message (#128) - fix(demo): add .gitignore to ai-chat, todo-list-mandu, island-first, ate-integration-test demos to prevent node_modules commit (#107)
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (11)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses seven distinct issues, enhancing the stability, security, and developer experience across various parts of the system. It includes critical fixes for HTML escaping in SSR, prevents infinite loops in streaming SSR, and mitigates XSS risks in the development environment. Additionally, it refines logging for CSS processes, improves clarity in dev server warnings, and streamlines demo project management by adding appropriate Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request effectively addresses seven identified issues, improving the stability, security, and user experience of the application. Key improvements include fixing an XSS vulnerability in the dev error overlay, preventing infinite recursion with circular references in streaming SSR, and correcting HTML escaping for title content. The addition of .gitignore files to demo projects is also a good practice.
Note: Security Review is unavailable for this PR.
| const h2 = document.createElement('h2'); | ||
| h2.style.cssText = 'color:#ff6b6b;margin:0 0 20px;'; | ||
| h2.textContent = '🔥 Build Error'; | ||
| const pre = document.createElement('pre'); | ||
| pre.style.cssText = 'white-space:pre-wrap;word-break:break-all;'; | ||
| pre.textContent = message || 'Unknown error'; | ||
| const btn = document.createElement('button'); | ||
| btn.style.cssText = 'position:fixed;top:20px;right:20px;background:#333;color:#fff;border:none;padding:10px 20px;cursor:pointer;'; | ||
| btn.textContent = 'Close'; | ||
| btn.onclick = function() { overlay.remove(); }; | ||
| overlay.appendChild(h2); | ||
| overlay.appendChild(pre); | ||
| overlay.appendChild(btn); |
There was a problem hiding this comment.
Replacing innerHTML with document.createElement and textContent is a critical security improvement. This change effectively mitigates a potential Cross-Site Scripting (XSS) vulnerability by ensuring that user-provided or dynamic content is treated as plain text rather than executable HTML, preventing malicious script injection.
| */ | ||
| function isJSONSerializable(value: unknown, path: string = "root", isDev: boolean = false): { valid: boolean; issues: string[] } { | ||
| const issues: string[] = []; | ||
| const seen = new WeakSet<object>(); |
There was a problem hiding this comment.
| // 순환 참조 감지 — 무한 재귀 방지 | ||
| if (seen.has(val as object)) { | ||
| issues.push(`${currentPath}: 순환 참조가 감지되었습니다 (JSON 직렬화 불가)`); | ||
| return; | ||
| } | ||
| seen.add(val as object); |
There was a problem hiding this comment.
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| <title>${escapeHtmlAttr(title)}</title> | ||
| <title>${escapeHtmlText(title)}</title> |
There was a problem hiding this comment.
Using escapeHtmlText instead of escapeHtmlAttr for the <title> tag content is the correct approach. The <title> element contains plain text, not an attribute value, so attribute-specific escaping (which handles quotes) is unnecessary and can lead to incorrect rendering of characters like single or double quotes in the browser tab.