From f8352cfe5baa695bd2672e0f4be6f70c750cba98 Mon Sep 17 00:00:00 2001 From: 2alf Date: Mon, 22 Dec 2025 19:35:41 +0100 Subject: [PATCH] XSS fix - Bug: xss vector in the "Target URL *" field on `/requests`. - Fix: added a regex validator on submition for http and https only for leaks.ts and requests.ts --- convex/leaks.ts | 7 +++++++ convex/requests.ts | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/convex/leaks.ts b/convex/leaks.ts index 445e91e..92bb903 100644 --- a/convex/leaks.ts +++ b/convex/leaks.ts @@ -236,6 +236,13 @@ export const insertLeak = mutation({ }; } + if (args.url && !/^https?:\/\/.+/i.test(args.url)) { + return { + success: false as const, + error: "Invalid URL.", + }; + } + // Validate required fields if (!args.targetName || !args.provider || !args.leakText) { return { diff --git a/convex/requests.ts b/convex/requests.ts index 326dbff..47c581a 100644 --- a/convex/requests.ts +++ b/convex/requests.ts @@ -3,6 +3,13 @@ import { getAuthUserId } from "@convex-dev/auth/server"; import { query, mutation } from "./_generated/server"; import { Id } from "./_generated/dataModel"; +// url validation helper +function isValidUrl(url: string): boolean { + return /^https?:\/\/.+/i.test(url); // only http and https +} + + + /** * Get all open (non-closed) requests from the database. * Returns requests with submitter names populated. @@ -104,6 +111,7 @@ export const getUserOpenRequests = query({ }, }); + /** * Create a new request for a leak target. * Validates that: @@ -147,6 +155,13 @@ export const createRequest = mutation({ }; } + if (!isValidUrl(args.targetUrl)) { + return { + success: false as const, + error: "The provided target URL is not valid. Please provide a valid URL starting with http:// or https://", + }; + } + // Check if a request with the same target name already exists (case-insensitive) // Query ALL requests, not just open ones const allRequests = await ctx.db.query("requests").collect();