diff --git a/.jules/flash.md b/.jules/flash.md new file mode 100644 index 0000000..f96b26f --- /dev/null +++ b/.jules/flash.md @@ -0,0 +1,5 @@ +## 2024-05-18 - Unsanitized X-Forwarded-For injection vulnerability +**Category:** Security +**Finding:** `x-forwarded-for` header values were passed directly into Supabase insert operations without sanitization or `.trim()`. +**Learning:** Proxy chains can prepend multiple IPs or inject spaces in the `x-forwarded-for` header. Passing this unsanitized directly to database queries could trigger DoS via massive insertion limits or injection vulnerabilities. +**Action:** Always extract the client IP securely using `(ip || "").split(",")[0].trim()`. diff --git a/src/app/api/v1/payment-links/route.ts b/src/app/api/v1/payment-links/route.ts index aa7e98a..4f51f71 100644 --- a/src/app/api/v1/payment-links/route.ts +++ b/src/app/api/v1/payment-links/route.ts @@ -118,7 +118,7 @@ export async function POST(req: NextRequest) { method: 'POST', status_code: 201, request_body: body, - ip_address: clientIp.split(',')[0] + ip_address: clientIp.split(',')[0].trim() // eslint-disable-next-line @typescript-eslint/no-explicit-any }).then(({ error }: any) => { if(error) console.error('Failed to log API call', error) diff --git a/src/lib/api/verify-api-key.ts b/src/lib/api/verify-api-key.ts index 9b858a8..fc504ef 100644 --- a/src/lib/api/verify-api-key.ts +++ b/src/lib/api/verify-api-key.ts @@ -57,7 +57,7 @@ export async function verifyApiKey(req: NextRequest) { endpoint: req.nextUrl.pathname, method: req.method, status_code: 200, // Assumed success if we get here - ip_address: req.headers.get('x-forwarded-for') || 'unknown', + ip_address: (req.headers.get('x-forwarded-for') || 'unknown').split(',')[0].trim(), user_agent: req.headers.get('user-agent') || 'unknown' // eslint-disable-next-line @typescript-eslint/no-explicit-any }).then(({ error }: any) => { diff --git a/src/providers.tsx b/src/providers.tsx index 264c46a..aa435d8 100644 --- a/src/providers.tsx +++ b/src/providers.tsx @@ -14,7 +14,7 @@ import type { AppKitNetwork } from '@reown/appkit/networks' const queryClient = new QueryClient() const alchemyKey = process.env.NEXT_PUBLIC_ALCHEMY_KEY -const projectId = process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID || '' +const projectId = process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID || 'fallback-id' // Testnet keywords to filter out const TESTNET_KEYWORDS = [