fix(SEC-WEB-30+31+36): Validate JSON.parse/localStorage deserialization
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Add runtime type validation after all JSON.parse calls in the web app to prevent runtime crashes from corrupted or tampered storage data. Creates a shared safeJsonParse utility with type guard functions for each data shape (Message[], ChatOverlayState, LayoutConfigRecord). All four affected callsites now validate parsed data and fall back to safe defaults on mismatch. Files changed: - apps/web/src/lib/utils/safe-json.ts (new utility) - apps/web/src/lib/utils/safe-json.test.ts (25 tests) - apps/web/src/hooks/useChat.ts (deserializeMessages) - apps/web/src/hooks/useChat.test.ts (3 new corruption tests) - apps/web/src/hooks/useChatOverlay.ts (loadState) - apps/web/src/hooks/useChatOverlay.test.ts (3 new corruption tests) - apps/web/src/components/chat/ConversationSidebar.tsx (ideaToConversation) - apps/web/src/lib/hooks/useLayout.ts (layout loading) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, forwardRef, useImperativeHandle, useCallback } from "react";
|
||||
import { getConversations, type Idea } from "@/lib/api/ideas";
|
||||
import { useAuth } from "@/lib/auth/auth-context";
|
||||
import { safeJsonParse, isMessageArray } from "@/lib/utils/safe-json";
|
||||
|
||||
interface ConversationSummary {
|
||||
id: string;
|
||||
@@ -41,15 +41,9 @@ export const ConversationSidebar = forwardRef<ConversationSidebarRef, Conversati
|
||||
* Convert Idea to ConversationSummary
|
||||
*/
|
||||
const ideaToConversation = useCallback((idea: Idea): ConversationSummary => {
|
||||
// Count messages from the stored JSON content
|
||||
let messageCount = 0;
|
||||
try {
|
||||
const messages = JSON.parse(idea.content);
|
||||
messageCount = Array.isArray(messages) ? messages.length : 0;
|
||||
} catch {
|
||||
// If parsing fails, assume 0 messages
|
||||
messageCount = 0;
|
||||
}
|
||||
// Count messages from the stored JSON content with runtime validation
|
||||
const messages = safeJsonParse(idea.content, isMessageArray, []);
|
||||
const messageCount = messages.length;
|
||||
|
||||
return {
|
||||
id: idea.id,
|
||||
|
||||
Reference in New Issue
Block a user