Conversation
3ba305e to
108939f
Compare
222eba4 to
2bfb339
Compare
2bfb339 to
fb50fec
Compare
sdk/webpubsub-chat-client/examples/teams-lite/client/src/components/Sidebar.tsx
Fixed
Show fixed
Hide fixed
fb50fec to
c4ded8d
Compare
sdk/webpubsub-chat-client/examples/teams-lite/client/src/components/Sidebar.tsx
Fixed
Show fixed
Hide fixed
c4ded8d to
256538c
Compare
256538c to
27f1771
Compare
| const sender = lastMessage.sender || 'Unknown'; | ||
| // Strip HTML tags to get plain text | ||
| const rawContent = lastMessage.content; | ||
| const content = rawContent.replace(/<[^>]*>/g, '').replace(/ /g, ' ').trim(); |
Check failure
Code scanning / CodeQL
Incomplete multi-character sanitization High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 23 days ago
General approach: Avoid using a brittle custom regex to remove HTML. Instead, rely on a well‑tested library that safely strips or sanitizes HTML, or at minimum, use a function that repeatedly applies the regex until no changes occur (mitigating the “reappearing text” problem). Since this code only needs a plain‑text preview, a safe HTML‑to‑text conversion (strip all tags and decode entities) is ideal.
Best fix here: Use the popular sanitize-html npm package (already suggested in the background) or a similar well‑known library to normalize/sanitize the content once, then derive the preview from that sanitized text. To minimize behavior changes, we’ll:
- Import
sanitize-html. - Replace the current
rawContent.replace(/<[^>]*>/g, '').replace(/ /g, ' ').trim();with a call that:- Sanitizes the string by removing all tags.
- Replaces non‑breaking spaces with regular spaces.
- Trims the result.
Concretely, in sdk/webpubsub-chat-client/examples/teams-lite/client/src/components/Sidebar.tsx:
- Add an import for
sanitize-htmlat the top. - In
formatMessagePreview, change line 75 so that:- We call
sanitizeHtmlwithallowedTags: []andallowedAttributes: {}(strip all tags). - Then perform the existing
andtrimhandling.
- We call
No other logic (max length, private vs group, etc.) needs to change.
Methods/imports/definitions needed:
- Import:
import sanitizeHtml from 'sanitize-html'; - No additional helper methods are strictly required; we can inline the call in the existing function.
| @@ -7,6 +7,7 @@ | ||
| import { usePrivateChat } from '../hooks/usePrivateChat'; | ||
| import { AvatarWithOnlineStatus } from './AvatarWithOnlineStatus'; | ||
| import { GLOBAL_METADATA_ROOM_ID } from '../lib/constants'; | ||
| import sanitizeHtml from 'sanitize-html'; | ||
|
|
||
| export const Sidebar: React.FC = () => { | ||
| const settings = useContext(ChatSettingsContext); | ||
| @@ -70,9 +71,9 @@ | ||
| if (!lastMessage) return 'No messages yet'; | ||
|
|
||
| const sender = lastMessage.sender || 'Unknown'; | ||
| // Strip HTML tags to get plain text | ||
| // Strip HTML tags to get plain text using a robust sanitizer | ||
| const rawContent = lastMessage.content; | ||
| const content = rawContent.replace(/<[^>]*>/g, '').replace(/ /g, ' ').trim(); | ||
| const content = sanitizeHtml(rawContent || '', { allowedTags: [], allowedAttributes: {} }).replace(/ /g, ' ').trim(); | ||
| const maxLength = 20; // Adjust based on your UI needs | ||
| const isPrivateChat = roomId.startsWith('private-'); | ||
|
|
| @@ -27,7 +27,8 @@ | ||
| "roosterjs-content-model-api": "^9.45.2", | ||
| "roosterjs-content-model-core": "^9.45.2", | ||
| "roosterjs-content-model-plugins": "^9.45.2", | ||
| "roosterjs-react": "^9.0.4" | ||
| "roosterjs-react": "^9.0.4", | ||
| "sanitize-html": "^2.17.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@eslint/js": "^9.30.1", |
| Package | Version | Security advisories |
| sanitize-html (npm) | 2.17.0 | None |
| await chatClient.createRoom(`${userId} (You)`, [userId], selfChatRoomId); | ||
| } catch (err) { | ||
| // Room may already exist, ignore error | ||
| console.log(`Self-chat room for ${userId} may already exist:`, err.message); |
Check failure
Code scanning / CodeQL
Use of externally-controlled format string High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 23 days ago
General fix: Avoid building the format string itself from untrusted data. Instead, use a constant format string and supply untrusted values as additional arguments, typically with %s placeholders, or sanitize/escape any % characters before interpolating.
Best fix here: Change the console.log on line 45 so that the first argument is a constant string with a %s placeholder, and pass userId as the second argument. This keeps the same visible log message content but ensures untrusted data is treated purely as data, not as part of the format string.
Concrete change in sdk/webpubsub-chat-client/examples/teams-lite/server/index.js:
- Locate the
console.loginside thecatchblock around the self-chat room creation (currently using a template literal with${userId}). - Replace that template-literal usage with a constant format string:
"Self-chat room for %s may already exist:", and passuserIdas a separate argument, precedingerr.message. - No new imports or helper methods are required; this only changes the
console.logcall signature.
| @@ -42,7 +42,7 @@ | ||
| await chatClient.createRoom(`${userId} (You)`, [userId], selfChatRoomId); | ||
| } catch (err) { | ||
| // Room may already exist, ignore error | ||
| console.log(`Self-chat room for ${userId} may already exist:`, err.message); | ||
| console.log("Self-chat room for %s may already exist:", userId, err.message); | ||
| } | ||
| } | ||
| res.json({ |
No description provided.