Skip to content

Commit 0cc6f77

Browse files
committed
fix: enforce encrypted data validation to prevent plaintext exposure
1 parent fa93a7f commit 0cc6f77

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

src/lib/validation.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,14 @@ export const reorderFolderSchema = z.object({
3535
});
3636

3737
export const createNoteSchema = z.object({
38-
title: z.string().min(1).max(200).optional(),
39-
content: z.string().optional(),
38+
title: z.string().refine(
39+
(value) => value === "[ENCRYPTED]",
40+
"Title must be '[ENCRYPTED]'"
41+
).optional(),
42+
content: z.string().refine(
43+
(value) => value === "[ENCRYPTED]",
44+
"Content must be '[ENCRYPTED]'"
45+
).optional(),
4046
folderId: z.string().uuid().nullable().optional(),
4147
starred: z.boolean().optional(),
4248
tags: z.array(z.string().max(50)).max(20).optional(),
@@ -48,8 +54,14 @@ export const createNoteSchema = z.object({
4854
});
4955

5056
export const updateNoteSchema = z.object({
51-
title: z.string().min(1).max(200).optional(),
52-
content: z.string().optional(),
57+
title: z.string().refine(
58+
(value) => value === "[ENCRYPTED]",
59+
"Title must be '[ENCRYPTED]'"
60+
).optional(),
61+
content: z.string().refine(
62+
(value) => value === "[ENCRYPTED]",
63+
"Content must be '[ENCRYPTED]'"
64+
).optional(),
5365
folderId: z.string().uuid().nullable().optional(),
5466
starred: z.boolean().optional(),
5567
archived: z.boolean().optional(),

src/websocket/handlers/notes.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,15 @@ export class NoteHandler extends BaseResourceHandler {
9797

9898
Object.keys(message.changes).forEach(key => {
9999
if (allowedFields.includes(key)) {
100-
filteredChanges[key] = (message.changes as Record<string, unknown>)[key];
100+
const value = (message.changes as Record<string, unknown>)[key];
101+
102+
// Validate title and content fields must be [ENCRYPTED]
103+
if ((key === 'title' || key === 'content') && typeof value === 'string' && value !== '[ENCRYPTED]') {
104+
console.warn(`Note update: rejected plaintext ${key} for note ${message.noteId} - must be [ENCRYPTED]`);
105+
return;
106+
}
107+
108+
filteredChanges[key] = value;
101109
} else {
102110
console.warn(`Note update: filtered out disallowed field '${key}' for note ${message.noteId}`);
103111
}

0 commit comments

Comments
 (0)