Skip to content

🛡️ Sentinel: [HIGH] Fix Host-Header SSRF in bulk lookup API#146

Open
aicoder2009 wants to merge 1 commit into
mainfrom
sentinel/fix-bulk-lookup-ssrf-8579163770110542801
Open

🛡️ Sentinel: [HIGH] Fix Host-Header SSRF in bulk lookup API#146
aicoder2009 wants to merge 1 commit into
mainfrom
sentinel/fix-bulk-lookup-ssrf-8579163770110542801

Conversation

@aicoder2009
Copy link
Copy Markdown
Owner

@aicoder2009 aicoder2009 commented Jun 5, 2026

🛡️ Sentinel: [HIGH] Fix Host-Header SSRF in bulk lookup API

🚨 Severity: HIGH
💡 Vulnerability: The /api/lookup/bulk/route.ts API endpoint previously executed bulk requests by performing a loopback fetch() against its own dynamically generated origin (request.nextUrl.origin). This relies directly on the HTTP Host header provided by the user.
🎯 Impact: An attacker could manipulate the Host header to point to internal IP addresses or private network endpoints. The Next.js server would then execute the fetch request against that internal target, leading to a Server-Side Request Forgery (SSRF) vulnerability.
🔧 Fix: Refactored the route to directly import the internal POST handlers (url/route.ts, doi/route.ts, isbn/route.ts) and invoke them directly using a safe, synthetic NextRequest bound to http://localhost. This eliminates the loopback HTTP request entirely and removes any reliance on the Host header.
Verification: Verified by updating tests (src/app/api/lookup/bulk/route.test.ts) to mock the direct POST handler invocations instead of global.fetch, ensuring the core logic remains covered and regressions are avoided.


PR created automatically by Jules for task 8579163770110542801 started by @aicoder2009

Summary by CodeRabbit

  • Bug Fixes

    • Mitigated a Host-Header SSRF security vulnerability in the bulk lookup API
  • New Features

    • Bulk lookup API now enforces a maximum of 20 items per request
    • Enhanced input validation that automatically rejects empty items
    • Improved response structure with detailed success and failure counts

Removed unsafe loopback fetch() calls dependent on the user-controllable
Host header (`request.nextUrl.origin`) in the bulk lookup API. Instead,
directly imports and invokes the internal Next.js route handlers with a
safe, synthetic `NextRequest` object (`http://localhost`). This eliminates
the possibility of manipulating the host header to execute unintended
Server-Side Request Forgery (SSRF) requests to internal infrastructure.

Co-authored-by: aicoder2009 <127642633+aicoder2009@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 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 @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings June 5, 2026 07:26
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
opencitation Ready Ready Preview, Comment Jun 5, 2026 7:27am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

The PR mitigates a Host-Header SSRF vulnerability in the bulk lookup API by replacing unsafe fetch-based loopback requests with direct handler invocations using synthetic NextRequest objects targeting a hardcoded safe host. Tests are updated to mock sub-route handlers instead of global fetch, and security documentation is added.

Changes

SSRF Vulnerability Mitigation

Layer / File(s) Summary
Handler imports and direct invocation
src/app/api/lookup/bulk/route.ts
Imports URL/DOI/ISBN lookup handlers, updates per-item type detection to select handler functions instead of endpoint strings, and replaces fetch execution with direct handler invocation using a synthetic NextRequest targeting http://localhost.
Test updates for sub-route mocking
src/app/api/lookup/bulk/route.test.ts
Switches from mocking global fetch to mocking individual sub-route handler modules (../url/route, ../doi/route, ../isbn/route), then rewrites routing tests, summary-counts test, and mixed-batch test to assert handler invocations and control per-type mock responses.
Security documentation
.jules/sentinel.md
Documents the Host-Header SSRF vulnerability in the original fetch-based loopback implementation and the mitigation strategy of avoiding fetch by invoking handlers directly with a hardcoded safe host.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A request once roamed through unsafe hosts,
Till localhost secured what fetch had lost.
Direct handlers now in harmony play,
Headers tamed, threats washed away!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: fixing a Host-Header SSRF vulnerability in the bulk lookup API, which aligns with the primary security fix implemented across all three modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sentinel/fix-bulk-lookup-ssrf-8579163770110542801

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR mitigates a Host-header SSRF vulnerability in the bulk lookup API by removing loopback fetch() calls that relied on request.nextUrl.origin (user-controlled via Host) and instead directly invoking the internal lookup route handlers with a fixed-origin synthetic NextRequest.

Changes:

  • Replaced loopback HTTP fetch() calls in the bulk lookup route with direct imports/invocations of the URL/DOI/ISBN route POST handlers.
  • Constructed a synthetic NextRequest bound to http://localhost for internal handler calls to eliminate Host header influence.
  • Updated bulk lookup tests to mock the imported handlers instead of mocking global.fetch.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/app/api/lookup/bulk/route.ts Removes loopback fetch(request.nextUrl.origin + ...) and directly calls internal lookup handlers to prevent Host-header SSRF.
src/app/api/lookup/bulk/route.test.ts Updates tests to mock and assert direct handler invocation instead of mocking fetch.
.jules/sentinel.md Documents the Host-header SSRF vulnerability pattern and the prevention approach used here.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/app/api/lookup/bulk/route.ts (1)

57-60: ⚡ Quick win

src/app/api/lookup/bulk/route.ts: Content-Type for synthetic JSON request

  • In this repo’s existing API tests, new NextRequest(...) is constructed with a JSON-stringified body without setting Content-Type, indicating req.json() parsing doesn’t rely on it.
  • Add Content-Type: application/json only if the downstream lookup handlers explicitly read req.headers.get("content-type").
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/api/lookup/bulk/route.ts` around lines 57 - 60, The synthetic
NextRequest constructed as syntheticRequest = new NextRequest(...) is missing an
explicit Content-Type header; if any downstream lookup handlers read
req.headers.get("content-type") (or branch logic depends on that header) then
update the NextRequest init to include headers: { "content-type":
"application/json" } so req.json() consumers see the correct MIME type,
otherwise leave the existing construction unchanged—check the lookup handler
functions that consume the request to decide.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/app/api/lookup/bulk/route.ts`:
- Around line 57-60: The synthetic NextRequest constructed as syntheticRequest =
new NextRequest(...) is missing an explicit Content-Type header; if any
downstream lookup handlers read req.headers.get("content-type") (or branch logic
depends on that header) then update the NextRequest init to include headers: {
"content-type": "application/json" } so req.json() consumers see the correct
MIME type, otherwise leave the existing construction unchanged—check the lookup
handler functions that consume the request to decide.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 29b7c13f-39fc-4703-bc79-9424f11462c3

📥 Commits

Reviewing files that changed from the base of the PR and between b872925 and 8406d62.

📒 Files selected for processing (3)
  • .jules/sentinel.md
  • src/app/api/lookup/bulk/route.test.ts
  • src/app/api/lookup/bulk/route.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants