From b06adb8609b231ebf51652ae3dab0da5474a7728 Mon Sep 17 00:00:00 2001 From: kenneth Date: Thu, 12 Mar 2026 01:55:39 +0000 Subject: [PATCH] fix(backend): validate context key element types Reject booleans, nulls, and nested arrays in the key param. Only string, number, and plain objects with primitive values are accepted. Co-authored-by: Ona --- apps/aelis-backend/src/engine/http.test.ts | 20 ++++++++++++++++++++ apps/aelis-backend/src/engine/http.ts | 15 ++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/apps/aelis-backend/src/engine/http.test.ts b/apps/aelis-backend/src/engine/http.test.ts index e41d7b3..8a55b95 100644 --- a/apps/aelis-backend/src/engine/http.test.ts +++ b/apps/aelis-backend/src/engine/http.test.ts @@ -204,6 +204,26 @@ describe("GET /api/context", () => { expect(body.error).toContain("key") }) + test("returns 400 when key contains invalid element types", async () => { + const { app } = buildContextApp("user-1") + + const res = await app.request("/api/context?key=[true,null,[1,2]]") + + expect(res.status).toBe(400) + const body = (await res.json()) as { error: string } + expect(body.error).toContain("key") + }) + + test("returns 400 when key is an empty array", async () => { + const { app } = buildContextApp("user-1") + + const res = await app.request("/api/context?key=[]") + + expect(res.status).toBe(400) + const body = (await res.json()) as { error: string } + expect(body.error).toContain("key") + }) + test("returns 400 when match param is invalid", async () => { const { app } = buildContextApp("user-1") diff --git a/apps/aelis-backend/src/engine/http.ts b/apps/aelis-backend/src/engine/http.ts index e2bc2c8..af1a851 100644 --- a/apps/aelis-backend/src/engine/http.ts +++ b/apps/aelis-backend/src/engine/http.ts @@ -59,7 +59,7 @@ function handleGetContext(c: Context) { return c.json({ error: 'Invalid or missing "key" parameter: must be a JSON array' }, 400) } - if (!Array.isArray(parsed)) { + if (!Array.isArray(parsed) || parsed.length === 0 || !parsed.every(isContextKeyPart)) { return c.json({ error: 'Invalid or missing "key" parameter: must be a JSON array' }, 400) } @@ -103,3 +103,16 @@ function handleGetContext(c: Context) { return c.json({ match: "prefix", entries }) } + +/** Validates that a value is a valid ContextKeyPart (string, number, or plain object of primitives). */ +function isContextKeyPart(value: unknown): boolean { + if (typeof value === "string" || typeof value === "number") { + return true + } + if (typeof value === "object" && value !== null && !Array.isArray(value)) { + return Object.values(value).every( + (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean", + ) + } + return false +}