🛡️ Sentinel: [CRITICAL] Fix SSRF vulnerability in bulk lookup API#133
🛡️ Sentinel: [CRITICAL] Fix SSRF vulnerability in bulk lookup API#133aicoder2009 wants to merge 1 commit into
Conversation
Removed `fetch` calls utilizing `request.nextUrl.origin` inside the `src/app/api/lookup/bulk/route.ts` API route handler, as `nextUrl.origin` parses the user-controlled `Host` header. This exposes the internal network to Server-Side Request Forgery (SSRF) vulnerabilities. The solution directly imports the exported handlers and invokes them by creating a synthetic `NextRequest` instance, which avoids loopback HTTP requests entirely. Tests have been properly updated to mock internal handlers rather than relying on `global.fetch`. Co-authored-by: aicoder2009 <127642633+aicoder2009@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR removes a critical SSRF vector in the /api/lookup/bulk endpoint by eliminating internal loopback fetch() calls that previously relied on request.nextUrl.origin (derived from the user-controlled Host header). Instead, bulk lookups now directly invoke the internal Next.js route handlers for URL/DOI/ISBN lookups via synthetic NextRequest objects.
Changes:
- Replaced internal
fetch(${request.nextUrl.origin}${apiEndpoint})calls with direct invocation of imported route handlers (../url/route,../doi/route,../isbn/route). - Updated bulk lookup tests to mock internal route handlers rather than mocking
global.fetch. - Documented the SSRF lesson/prevention pattern in
.jules/sentinel.md.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/app/api/lookup/bulk/route.ts | Removes host-header-derived internal fetches and calls internal lookup handlers directly to prevent SSRF. |
| src/app/api/lookup/bulk/route.test.ts | Refactors tests to mock imported lookup handlers instead of global.fetch. |
| .jules/sentinel.md | Adds a write-up documenting the SSRF root cause and prevention approach for future reference. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
🚨 Severity: CRITICAL
💡 Vulnerability: The
/api/lookup/bulkAPI endpoint utilizedfetchappended withrequest.nextUrl.originto proxy requests to internal endpoints (like URL, DOI, or ISBN lookups). Becauserequest.nextUrl.originis directly derived from the incoming userHostheader, an attacker could manipulate it.🎯 Impact: Manipulating the host header would cause the Next.js server to issue internal loopback requests (SSRF) to any arbitrary attacker-controlled domain or internal service accessible by the backend, leading to information disclosure and firewall bypass.
🔧 Fix: Refactored
src/app/api/lookup/bulk/route.tsto directly import the internal API route handler modules (POSTfunctions from../url/route,../doi/route, etc.) and invoke them directly with a newly constructedNextRequestsynthetic request rather than performing a true networkfetch(). The tests were also refactored to mock the internal handlers directly rather thanglobal.fetch.✅ Verification: Verified that tests pass via
pnpm test. Code manually reviewed. No network requests are dispatched by the bulk lookup route anymore.PR created automatically by Jules for task 12824801053690868309 started by @aicoder2009