Skip to content

add TeamsLite demo for chat sdk#866

Closed
xingsy97 wants to merge 2 commits intomainfrom
s/chat-teams-demo
Closed

add TeamsLite demo for chat sdk#866
xingsy97 wants to merge 2 commits intomainfrom
s/chat-teams-demo

Conversation

@xingsy97
Copy link
Collaborator

No description provided.

@xingsy97 xingsy97 force-pushed the s/chat-teams-demo branch 2 times, most recently from 3ba305e to 108939f Compare December 30, 2025 08:45
@xingsy97 xingsy97 force-pushed the s/chat-teams-demo branch 2 times, most recently from 222eba4 to 2bfb339 Compare January 15, 2026 09:01
const sender = lastMessage.sender || 'Unknown';
// Strip HTML tags to get plain text
const rawContent = lastMessage.content;
const content = rawContent.replace(/<[^>]*>/g, '').replace(/&nbsp;/g, ' ').trim();

Check failure

Code scanning / CodeQL

Incomplete multi-character sanitization High

This string may still contain
<script
, which may cause an HTML element injection vulnerability.

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:

  1. Import sanitize-html.
  2. Replace the current rawContent.replace(/<[^>]*>/g, '').replace(/&nbsp;/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-html at the top.
  • In formatMessagePreview, change line 75 so that:
    • We call sanitizeHtml with allowedTags: [] and allowedAttributes: {} (strip all tags).
    • Then perform the existing &nbsp; and trim handling.

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.

Suggested changeset 2
sdk/webpubsub-chat-client/examples/teams-lite/client/src/components/Sidebar.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/sdk/webpubsub-chat-client/examples/teams-lite/client/src/components/Sidebar.tsx b/sdk/webpubsub-chat-client/examples/teams-lite/client/src/components/Sidebar.tsx
--- a/sdk/webpubsub-chat-client/examples/teams-lite/client/src/components/Sidebar.tsx
+++ b/sdk/webpubsub-chat-client/examples/teams-lite/client/src/components/Sidebar.tsx
@@ -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(/&nbsp;/g, ' ').trim();
+    const content = sanitizeHtml(rawContent || '', { allowedTags: [], allowedAttributes: {} }).replace(/&nbsp;/g, ' ').trim();
     const maxLength = 20; // Adjust based on your UI needs
     const isPrivateChat = roomId.startsWith('private-');
     
EOF
@@ -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(/&nbsp;/g, ' ').trim();
const content = sanitizeHtml(rawContent || '', { allowedTags: [], allowedAttributes: {} }).replace(/&nbsp;/g, ' ').trim();
const maxLength = 20; // Adjust based on your UI needs
const isPrivateChat = roomId.startsWith('private-');

sdk/webpubsub-chat-client/examples/teams-lite/client/package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/sdk/webpubsub-chat-client/examples/teams-lite/client/package.json b/sdk/webpubsub-chat-client/examples/teams-lite/client/package.json
--- a/sdk/webpubsub-chat-client/examples/teams-lite/client/package.json
+++ b/sdk/webpubsub-chat-client/examples/teams-lite/client/package.json
@@ -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",
EOF
@@ -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",
This fix introduces these dependencies
Package Version Security advisories
sanitize-html (npm) 2.17.0 None
Copilot is powered by AI and may make mistakes. Always verify output.
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

Format string depends on a
user-provided value
.

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.log inside the catch block 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 pass userId as a separate argument, preceding err.message.
  • No new imports or helper methods are required; this only changes the console.log call signature.

Suggested changeset 1
sdk/webpubsub-chat-client/examples/teams-lite/server/index.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/sdk/webpubsub-chat-client/examples/teams-lite/server/index.js b/sdk/webpubsub-chat-client/examples/teams-lite/server/index.js
--- a/sdk/webpubsub-chat-client/examples/teams-lite/server/index.js
+++ b/sdk/webpubsub-chat-client/examples/teams-lite/server/index.js
@@ -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({
EOF
@@ -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({
Copilot is powered by AI and may make mistakes. Always verify output.
@xingsy97 xingsy97 closed this Feb 10, 2026
@xingsy97 xingsy97 deleted the s/chat-teams-demo branch February 10, 2026 09:09
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