From 71b6e9c88868489f87855111dfa0d84c6b7f5e38 Mon Sep 17 00:00:00 2001
From: Benedict Balogun <50557035+wolfyres@users.noreply.github.com>
Date: Mon, 27 Jul 2026 22:44:30 +0100
Subject: [PATCH 1/8] Create SECURITY.md
---
tools/v1/team/shared-team-inbox/SECURITY.md | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 tools/v1/team/shared-team-inbox/SECURITY.md
diff --git a/tools/v1/team/shared-team-inbox/SECURITY.md b/tools/v1/team/shared-team-inbox/SECURITY.md
new file mode 100644
index 000000000..ee18f5eba
--- /dev/null
+++ b/tools/v1/team/shared-team-inbox/SECURITY.md
@@ -0,0 +1,16 @@
+# Threat Model & Safety Assumptions: Shared Team Inbox (V1)
+
+## 1. Threat Assumptions & Vectors
+
+| Threat Vector | Source | Impact | Mitigation Strategy |
+| :--- | :--- | :--- | :--- |
+| **XSS / HTML Injection** | Malicious email body / headers | Execution of arbitrary JavaScript in team context | Strict HTML sanitization; stripping dangerous tags (` World';
+ expect(sanitizeMessageBody(hostile)).toBe('Hello [REDACTED SCRIPT] World');
+ });
+
+ it('strips event handlers and javascript URIs', () => {
+ const hostile = 'Click me';
+ const sanitized = sanitizeMessageBody(hostile);
+ expect(sanitized).not.toContain('onclick');
+ expect(sanitized).not.toContain('javascript:');
+ });
+
+ it('sanitizes malicious filenames', () => {
+ expect(sanitizeFilename('../../../etc/passwd')).toBe('.._.._.._etc_passwd');
+ });
+ });
+
+ describe('Performance Safeguards', () => {
+ it('enforces maximum pagination bounds of 50 items', () => {
+ const dummyList = Array.from({ length: 120 }, (_, i) => ({
+ id: `msg-${i}`,
+ teamId: 'team-1',
+ sender: 'test@example.com',
+ subject: `Subj ${i}`,
+ body: 'Body',
+ timestamp: Date.now(),
+ attachments: [],
+ }));
+
+ const page1 = paginateInboxMessages(dummyList, 1, 100); // requested 100
+ expect(page1.items.length).toBe(50); // bounded to max 50
+ expect(page1.hasMore).toBe(true);
+ });
+
+ it('truncates bodies exceeding character limits', () => {
+ const hugeBody = 'A'.repeat(150000);
+ const { text, isTruncated } = truncateLargeBody(hugeBody, 100000);
+ expect(isTruncated).toBe(true);
+ expect(text).toContain('[Content truncated for performance size limit]');
+ });
+ });
+});