gpt-engineer-app[bot] commited on
Commit
1c1086c
Β·
1 Parent(s): c9b513f
Files changed (1) hide show
  1. src/server/forensic.functions.ts +40 -0
src/server/forensic.functions.ts CHANGED
@@ -1,6 +1,46 @@
1
  import { createServerFn } from "@tanstack/react-start";
2
  import { z } from "zod";
3
  import { sanitize, restore } from "./branch-debug.functions";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  // ───────────────────────── Types ─────────────────────────
6
 
 
1
  import { createServerFn } from "@tanstack/react-start";
2
  import { z } from "zod";
3
  import { sanitize, restore } from "./branch-debug.functions";
4
+ import { requireSupabaseAuth } from "@/integrations/supabase/auth-middleware";
5
+
6
+ // ───────────────────────── SSRF Guard ─────────────────────────
7
+ // Reject loopback, private (RFC1918), link-local, and cloud metadata addresses
8
+ // before any server-side fetch of a user-supplied URL.
9
+ function assertSafePublicUrl(raw: string): URL {
10
+ let u: URL;
11
+ try { u = new URL(raw); } catch { throw new Response("Invalid URL", { status: 400 }); }
12
+ if (u.protocol !== "https:" && u.protocol !== "http:") {
13
+ throw new Response("Only http(s) URLs are allowed", { status: 400 });
14
+ }
15
+ const host = u.hostname.toLowerCase();
16
+ // Block obvious literals
17
+ const blockedHosts = new Set([
18
+ "localhost", "127.0.0.1", "0.0.0.0", "::1",
19
+ "169.254.169.254", "metadata.google.internal", "metadata.goog",
20
+ ]);
21
+ if (blockedHosts.has(host)) throw new Response("Host not allowed", { status: 400 });
22
+ // Block IPv4 private/reserved ranges
23
+ const ipv4 = host.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
24
+ if (ipv4) {
25
+ const [a, b] = ipv4.slice(1).map(Number);
26
+ if (
27
+ a === 10 ||
28
+ a === 127 ||
29
+ a === 0 ||
30
+ (a === 172 && b >= 16 && b <= 31) ||
31
+ (a === 192 && b === 168) ||
32
+ (a === 169 && b === 254) ||
33
+ a >= 224 // multicast/reserved
34
+ ) throw new Response("Private/reserved IP not allowed", { status: 400 });
35
+ }
36
+ // Block IPv6 loopback / link-local / unique-local
37
+ if (host.includes(":")) {
38
+ if (host === "::1" || host.startsWith("fe80:") || host.startsWith("fc") || host.startsWith("fd")) {
39
+ throw new Response("Private IPv6 not allowed", { status: 400 });
40
+ }
41
+ }
42
+ return u;
43
+ }
44
 
45
  // ───────────────────────── Types ─────────────────────────
46