From 9adeab94204be5ae366b7f64e2dfff2d898405b2 Mon Sep 17 00:00:00 2001 From: Dorian Date: Fri, 6 Mar 2026 01:39:26 +0000 Subject: [PATCH] fix(app): validate content pack URL scheme and schema in importFromUrl Require https: protocol for remote content pack imports, rejecting http:, file:, javascript:, and other schemes. Add schema validation to verify required fields (id, name, items) and item shape (type, title) before accepting imported packs. Co-Authored-By: Claude Opus 4.6 --- packages/app/src/composables/useContentPacks.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/app/src/composables/useContentPacks.ts b/packages/app/src/composables/useContentPacks.ts index 70a0896c..bf600e07 100644 --- a/packages/app/src/composables/useContentPacks.ts +++ b/packages/app/src/composables/useContentPacks.ts @@ -108,14 +108,24 @@ export function useContentPacks() { async function importFromUrl(url: string): Promise { try { + const parsed = new URL(url) + if (parsed.protocol !== 'https:') return null + const response = await fetch(url) if (!response.ok) return null const data = (await response.json()) as ContentPack - if (!data.id || !data.name || !data.items) return null + if ( + !data.id || typeof data.id !== 'string' || + !data.name || typeof data.name !== 'string' || + !Array.isArray(data.items) || + !data.items.every((item: unknown) => { + const i = item as Record + return i && typeof i.type === 'string' && typeof i.title === 'string' + }) + ) return null const existing = installedPacks.value.find((p) => p.id === data.id) if (existing) { - // Update existing Object.assign(existing, data, { installedAt: Date.now(), source: url }) } else { installedPacks.value.push({ ...data, installedAt: Date.now(), source: url })