diff --git a/.changeset/bright-facts-taste.md b/.changeset/bright-facts-taste.md new file mode 100644 index 0000000..97f4118 --- /dev/null +++ b/.changeset/bright-facts-taste.md @@ -0,0 +1,5 @@ +--- +"@emdash-cms/plugin-forms": patch +--- + +Fix DOM XSS in form redirects diff --git a/packages/plugins/forms/src/client/index.ts b/packages/plugins/forms/src/client/index.ts index 9917400..219326a 100644 --- a/packages/plugins/forms/src/client/index.ts +++ b/packages/plugins/forms/src/client/index.ts @@ -137,7 +137,13 @@ async function handleSubmit(e: Event) { if (result.success) { clearSavedState(form); if (result.redirect) { - window.location.href = result.redirect; + // prevent xss + if (isSafeRedirectUrl(result.redirect)) { + window.location.href = result.redirect; + } else { + showStatus(form, result.message || "Submitted successfully.", "success"); + form.reset(); + } } else { showStatus(form, result.message || "Submitted successfully.", "success"); form.reset(); @@ -157,6 +163,16 @@ async function handleSubmit(e: Event) { } } +/** validates that a redirect url uses a safe protocol */ +function isSafeRedirectUrl(url: string): boolean { + try { + const parsed = new URL(url, window.location.href); + return ["http:", "https:", "mailto:", "tel:"].includes(parsed.protocol); + } catch { + return false; + } +} + // ─── Click Handler (Prev/Next) ─────────────────────────────────── function handleClick(e: Event) {