From bc84907b84535bba43e8aecc60f0cee03d1857ab Mon Sep 17 00:00:00 2001 From: JohnDoe6345789 Date: Fri, 26 Dec 2025 01:15:02 +0000 Subject: [PATCH] docs: tsx,powertransfertab,packages (3 files) --- dbal/docs/CVE_ANALYSIS_2025_12.md | 101 ++++++++++++++++-- .../level5/PowerTransferTab.test.tsx | 9 +- .../forum_forge/static_content/examples.json | 62 +++++++++++ 3 files changed, 163 insertions(+), 9 deletions(-) diff --git a/dbal/docs/CVE_ANALYSIS_2025_12.md b/dbal/docs/CVE_ANALYSIS_2025_12.md index 49a9b46cd..f81decff6 100644 --- a/dbal/docs/CVE_ANALYSIS_2025_12.md +++ b/dbal/docs/CVE_ANALYSIS_2025_12.md @@ -213,14 +213,103 @@ private handleMessage(data: string): void { - Could modify Object prototype affecting all objects in process - Pattern: CVE-2019-10744 (lodash prototype pollution) -**Recommendation**: +**🏰 Fort Knox Remediation**: ```typescript -import { safeJsonParse } from './security-utils' +/** + * Fort Knox JSON Parser + * - Blocks prototype pollution + * - Enforces depth limits + * - Validates structure against schema + * - Sanitizes string content + */ +class SecureJsonParser { + private static readonly MAX_DEPTH = 10 + private static readonly MAX_STRING_LENGTH = 1_000_000 // 1MB + private static readonly MAX_ARRAY_LENGTH = 10_000 + private static readonly MAX_OBJECT_KEYS = 1000 + + private static readonly FORBIDDEN_KEYS = new Set([ + '__proto__', + 'constructor', + 'prototype', + '__defineGetter__', + '__defineSetter__', + '__lookupGetter__', + '__lookupSetter__', + ]) + + static parse(json: string, schema?: ZodSchema): T { + // 1. Length check + if (json.length > this.MAX_STRING_LENGTH) { + throw DBALError.validationError('JSON input too large', [ + { field: 'json', error: `Max ${this.MAX_STRING_LENGTH} bytes` } + ]) + } + + // 2. Parse with reviver for prototype protection + let depth = 0 + const parsed = JSON.parse(json, (key, value) => { + // Block dangerous keys + if (this.FORBIDDEN_KEYS.has(key)) { + throw DBALError.maliciousCode(`Forbidden key in JSON: ${key}`) + } + + // Track and limit depth + if (typeof value === 'object' && value !== null) { + depth++ + if (depth > this.MAX_DEPTH) { + throw DBALError.validationError('JSON nesting too deep') + } + + // Limit object keys + if (!Array.isArray(value) && Object.keys(value).length > this.MAX_OBJECT_KEYS) { + throw DBALError.validationError('Too many object keys') + } + + // Limit array length + if (Array.isArray(value) && value.length > this.MAX_ARRAY_LENGTH) { + throw DBALError.validationError('Array too large') + } + } + + return value + }) + + // 3. Validate against schema if provided + if (schema) { + const result = schema.safeParse(parsed) + if (!result.success) { + throw DBALError.validationError('Schema validation failed', + result.error.issues.map(i => ({ field: i.path.join('.'), error: i.message })) + ) + } + return result.data + } + + // 4. Deep freeze to prevent mutation + return this.deepFreeze(parsed) + } + + private static deepFreeze(obj: T): T { + if (obj === null || typeof obj !== 'object') return obj + + Object.freeze(obj) + Object.getOwnPropertyNames(obj).forEach(prop => { + const value = (obj as any)[prop] + if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) { + this.deepFreeze(value) + } + }) + + return obj + } +} -const response = safeJsonParse(data, { - protoAction: 'remove', - constructorAction: 'remove' -}) +// Usage in WebSocket bridge +private handleMessage(data: string): void { + const response = SecureJsonParser.parse(data, RPCResponseSchema) + // response is now validated, frozen, and safe +} ``` --- diff --git a/frontends/nextjs/src/components/level5/PowerTransferTab.test.tsx b/frontends/nextjs/src/components/level5/PowerTransferTab.test.tsx index ea26c6d40..16d27f4fb 100644 --- a/frontends/nextjs/src/components/level5/PowerTransferTab.test.tsx +++ b/frontends/nextjs/src/components/level5/PowerTransferTab.test.tsx @@ -31,11 +31,14 @@ const renderComponent = (overrides?: { onInitiate?: () => void }) => { return { onInitiateTransfer } } -const mockFetch = (payload: any) => - vi.stubGlobal('fetch', async () => ({ +const mockFetch = (payload: any) => { + const fetchMock = vi.fn(async () => ({ ok: true, json: async () => payload, })) + vi.stubGlobal('fetch', fetchMock) + return fetchMock +} afterEach(() => { vi.restoreAllMocks() @@ -71,7 +74,7 @@ describe('PowerTransferTab', () => { const { onInitiateTransfer } = renderComponent() - await waitFor(() => expect(screen.getByText(/Select User/i)).toBeInTheDocument()) + await screen.findByText(/Select User/i) fireEvent.click(screen.getByText('target-god')) const actionButton = screen.getByRole('button', { name: /Initiate Power Transfer/i }) diff --git a/packages/forum_forge/static_content/examples.json b/packages/forum_forge/static_content/examples.json index e1b75a994..600e4006f 100644 --- a/packages/forum_forge/static_content/examples.json +++ b/packages/forum_forge/static_content/examples.json @@ -10,6 +10,26 @@ "id": "cat_growth", "name": "Growth Ops", "description": "Retention, onboarding, and community tactics" + }, + { + "id": "cat_design", + "name": "Design Systems", + "description": "Tokens, theming, and UI governance" + }, + { + "id": "cat_ai", + "name": "AI Tooling", + "description": "Prompt playbooks, evals, and guardrails" + }, + { + "id": "cat_ops", + "name": "Community Ops", + "description": "Moderation workflows and engagement rituals" + }, + { + "id": "cat_hiring", + "name": "Hiring & Ops", + "description": "Team growth, planning, and operating cadence" } ], "threads": [ @@ -26,6 +46,48 @@ "categoryId": "cat_launch", "replyCount": 18, "likeCount": 64 + }, + { + "id": "thread_3", + "title": "Building a tokenized design system", + "categoryId": "cat_design", + "replyCount": 27, + "likeCount": 88 + }, + { + "id": "thread_4", + "title": "How to measure community health", + "categoryId": "cat_ops", + "replyCount": 33, + "likeCount": 96 + }, + { + "id": "thread_5", + "title": "Prompt playbooks for onboarding", + "categoryId": "cat_ai", + "replyCount": 21, + "likeCount": 54 + }, + { + "id": "thread_6", + "title": "Moderation handoff checklists", + "categoryId": "cat_ops", + "replyCount": 19, + "likeCount": 41 + }, + { + "id": "thread_7", + "title": "Hiring your first community lead", + "categoryId": "cat_hiring", + "replyCount": 15, + "likeCount": 33 + }, + { + "id": "thread_8", + "title": "Feature flag cadence for launches", + "categoryId": "cat_launch", + "replyCount": 12, + "likeCount": 29 } ] }