T09 · Insecure Skill Coding Practices
- Location
references/streaming.md:712- Finding
Unvalidated Client-Controlled Chat Messages Persisted to Storage
- Content
View full analysis
{ if (part.type === 'start') { return { createdAt: Date.now() }; } }, onFinish: async ({ messages }) => { await saveChat(chatId, messages); } }); } ``` ### Technical Analysis The documented server route reads `messages` and `chatId` directly from attacker-controlled request JSON. It then passes the messages to `convertToModelMessages` and ultimately persists the conversation through `saveChat` without first calling `validateUIMessages` or applying equivalent strict schemas. This contradicts the Skill's own persistence gate in `SKILL.md:272-273`, which requires validation before client-supplied messages are written to storage. TypeScript types do not protect this runtime boundary because arbitrary HTTP clients can submit malformed objects, unsupported message parts, forged metadata, oversized content, or unexpected tool and data structures. The audit cannot determine whether `saveChat` independently performs validation or authorization because its ...[truncated 1822 chars]- Remediation
View remediation
{ const messagesToSave = await validateUIMessages({ messages, tools, metadataSchema, dataSchemas }); await saveChat(body.chatId, currentUser.id, messagesToSave); } }); } ``` ]]>
