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();