Skip to content

🛡️ Sentinel: [HIGH] Fix Missing CSRF Protection on Mutating API Routes#143

Open
aicoder2009 wants to merge 1 commit into
mainfrom
sentinel-csrf-protection-8950450425632066895
Open

🛡️ Sentinel: [HIGH] Fix Missing CSRF Protection on Mutating API Routes#143
aicoder2009 wants to merge 1 commit into
mainfrom
sentinel-csrf-protection-8950450425632066895

Conversation

@aicoder2009

@aicoder2009 aicoder2009 commented Jun 3, 2026

Copy link
Copy Markdown
Owner

🚨 Severity: HIGH
💡 Vulnerability: Next.js Route Handlers do not automatically protect against CSRF attacks. Several core authenticated POST endpoints (creating lists, projects, citations, and share links) lacked the isSameOrigin check, meaning an attacker could potentially forge a cross-origin request using an authenticated user's session to perform unauthorized state mutations.
🎯 Impact: An attacker could trick a logged-in user into visiting a malicious site that sends POST requests to the OpenCitation API, creating lists, projects, or share links without their explicit consent.
🔧 Fix: Imported and enforced the existing isSameOrigin utility check from @/lib/security/rate-limit.ts to block cross-origin POSTs across all vulnerable endpoints, returning a 403 Forbidden response.
Verification: Verified via pnpm test (tests updated with mocked CSRF check) and visual inspection of route handlers.


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

Summary by CodeRabbit

  • New Features

    • API endpoints now include origin validation checks on all POST operations throughout the application. Requests from invalid origin sources receive a 403 Forbidden response. This validation applies to project creation, list management, citation handling, and content sharing features.
  • Tests

    • Updated test suite infrastructure with proper mocking for request origin validation checks.

Added `isSameOrigin` validation from `@/lib/security/rate-limit` to the following state-mutating POST endpoints:
- `/api/lists`
- `/api/lists/[id]/citations`
- `/api/projects`
- `/api/projects/[id]/lists`
- `/api/share`
- `/api/share/[code]/clone`

This prevents cross-origin requests from forging state changes on behalf of an authenticated user. Included mocked tests to ensure proper execution.

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 3, 2026 06:41
@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
opencitation Ready Ready Preview, Comment Jun 3, 2026 6:42am

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This pull request adds same-origin validation to six mutating API route handlers to prevent CSRF attacks. An isSameOrigin guard is imported and applied to POST endpoints across lists, projects, and share routes, returning 403 Forbidden for cross-origin requests. Test suites mock the validation for isolation.

Changes

CSRF Protection via Same-Origin Validation

Layer / File(s) Summary
Vulnerability Documentation
.jules/sentinel.md
Sentinel entry documents the missing CSRF protection issue on mutating routes and describes the isSameOrigin validation mitigation.
Origin Validation Implementation Across Routes
src/app/api/lists/[id]/citations/route.ts, src/app/api/lists/route.ts, src/app/api/projects/[id]/lists/route.ts, src/app/api/projects/route.ts, src/app/api/share/[code]/clone/route.ts, src/app/api/share/route.ts
isSameOrigin is imported from the security module and used to validate request origin in all POST handlers. Requests failing the check receive 403 Forbidden responses. The share clone route updates its request type to NextRequest.
Test Mocks for Rate-Limit Module
src/app/api/lists/[id]/citations/route.test.ts, src/app/api/lists/route.test.ts, src/app/api/projects/[id]/lists/route.test.ts, src/app/api/projects/route.test.ts, src/app/api/share/route.test.ts
Vitest mocks for @/lib/security/rate-limit stub isSameOrigin to always return true, isolating tests from the actual origin validation logic.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 With origins checked and requests true,
Cross-site forgeries can't slip through,
Same-source validation stands the test,
Security serves all routes the best. 🛡️

🚥 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 references the main change—implementing CSRF protection on mutating API routes—which is the core objective of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
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-csrf-protection-8950450425632066895

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

Copilot AI left a comment

Copy link
Copy Markdown

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 hardens several authenticated, state-mutating Next.js Route Handlers against CSRF by enforcing the existing isSameOrigin check before processing POST bodies, returning 403 Forbidden for cross-origin requests.

Changes:

  • Enforced isSameOrigin on multiple mutating API endpoints (lists, projects, citations, share links, and share cloning).
  • Updated Vitest route-handler tests to mock the new CSRF guard so existing test cases continue to run.
  • Documented the CSRF finding and prevention guidance in the Jules Sentinel log.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/app/api/share/route.ts Adds same-origin CSRF enforcement to share-link creation.
src/app/api/share/route.test.ts Mocks CSRF guard for share route tests (needs explicit 403-path coverage).
src/app/api/share/[code]/clone/route.ts Adds CSRF enforcement and changes handler request type to NextRequest (currently introduces a duplicate import lint error).
src/app/api/projects/route.ts Adds same-origin CSRF enforcement to project creation.
src/app/api/projects/route.test.ts Mocks CSRF guard for projects route tests (needs explicit 403-path coverage).
src/app/api/projects/[id]/lists/route.ts Adds same-origin CSRF enforcement to list creation under a project.
src/app/api/projects/[id]/lists/route.test.ts Mocks CSRF guard for project-lists route tests (needs explicit 403-path coverage).
src/app/api/lists/route.ts Adds same-origin CSRF enforcement to list creation.
src/app/api/lists/route.test.ts Mocks CSRF guard for lists route tests (needs explicit 403-path coverage).
src/app/api/lists/[id]/citations/route.ts Adds same-origin CSRF enforcement to adding a citation to a list.
src/app/api/lists/[id]/citations/route.test.ts Mocks CSRF guard for citations route tests (needs explicit 403-path coverage).
.jules/sentinel.md Adds Sentinel entry documenting the CSRF issue and prevention guidance (date appears to have an incorrect year).

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

Comment on lines +18 to 20
import { isSameOrigin } from "@/lib/security/rate-limit";
import { NextRequest } from "next/server";

Comment thread .jules/sentinel.md
**Learning:** `marked` does not sanitize HTML by default. While this may seem safe for trusted inputs (like internal docs or GitHub releases), if malicious input manages to enter these sources, it leads directly to an XSS vulnerability.
**Prevention:** The output of `marked` (or any markdown parser) must always be wrapped with `DOMPurify.sanitize()` (using `isomorphic-dompurify` for SSR) before being passed to `dangerouslySetInnerHTML`.

## 2024-06-03 - Missing CSRF Protection on Mutating API Routes
Comment on lines +5 to +9
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
rateLimit: vi.fn(() => ({ ok: true })),
getClientKey: vi.fn(),
}));
Comment on lines +5 to +7
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
}));
Comment on lines +5 to +7
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
}));
Comment on lines +5 to +7
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
}));
Comment on lines +5 to +7
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
}));

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/app/api/share/[code]/clone/route.ts (1)

2-2: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Merge duplicate next/server import.

NextRequest is imported separately on Line 19 while NextResponse is already imported from next/server on Line 2. ESLint flags this (no-duplicate-imports / import/no-duplicates); consolidate into a single import.

🔧 Proposed fix
-import { NextResponse } from "next/server";
+import { NextRequest, NextResponse } from "next/server";
 import {
   getShareLink,
   findListById,
@@
 import { parseShareSegment } from "`@/lib/share-utils`";
 import { verifySharePassword } from "`@/lib/share-password`";
 import { isSameOrigin } from "`@/lib/security/rate-limit`";
-import { NextRequest } from "next/server";

Also applies to: 19-19

🤖 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/share/`[code]/clone/route.ts at line 2, Consolidate the duplicate
imports from "next/server" by importing both NextRequest and NextResponse in a
single statement (replace the separate NextRequest import with a combined import
like import { NextRequest, NextResponse } from "next/server"); remove the
redundant import so only one import from "next/server" remains and update any
references to NextRequest/NextResponse accordingly.
🤖 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.

Inline comments:
In `@src/app/api/lists/`[id]/citations/route.test.ts:
- Around line 5-7: Tests currently mock isSameOrigin to always return true, so
there is no coverage that cross-origin POSTs are rejected; add a test in the
POST /api/lists/[id]/citations suite that temporarily mocks the isSameOrigin
guard to return false (using vi.fn or vi.mock), performs a POST to the route
handler, and asserts the response status is 403 Forbidden and body contains the
CSRF error. Target the isSameOrigin mock from "`@/lib/security/rate-limit`" and
update/restore the mock inside the test so other tests are unaffected.

In `@src/app/api/lists/route.test.ts`:
- Around line 5-7: Add a test in src/app/api/lists/route.test.ts that verifies
CSRF protection by making a cross-origin POST to the POST /api/lists route with
isSameOrigin mocked to return false; specifically, temporarily override the
existing vi.mock/vi.fn for isSameOrigin (or use vi.spyOn) to return false,
perform the POST call used by the suite, and assert the response status is 403
Forbidden; restore/reset the mock after the test to avoid affecting other tests.

In `@src/app/api/projects/`[id]/lists/route.test.ts:
- Around line 5-7: Add a test in the POST /api/projects/[id]/lists suite in
route.test.ts that verifies CSRF/origin protection by setting the mocked
isSameOrigin to return false (use the same "`@/lib/security/rate-limit`" mock and
mutate its isSameOrigin mock to false), perform a POST to the route under test,
and assert the response is rejected (e.g., status 403 and an error body
indicating CSRF/origin failure); restore or reset the isSameOrigin mock to its
original true behavior after the test so other tests remain unaffected.

In `@src/app/api/projects/route.test.ts`:
- Around line 5-7: Add a test in src/app/api/projects/route.test.ts inside the
"POST /api/projects" suite that verifies the CSRF guard rejects cross-origin
requests: update or add a mock for the isSameOrigin function (used in the
vi.mock("`@/lib/security/rate-limit`") setup) to return false for the cross-origin
case, perform a POST to the /api/projects route with a non-same-origin header,
and assert the response status is 403 Forbidden; ensure the test uses the
existing test helpers/setup in the file and restores the original mock behavior
after the case so other tests remain unaffected.

In `@src/app/api/share/route.test.ts`:
- Around line 5-9: The test suite currently mocks isSameOrigin to always return
true, so add a test in the POST /api/share suite that sets the isSameOrigin mock
to return false (e.g., vi.mock or isSameOrigin.mockReturnValueOnce(false)),
issues a POST to the /api/share route, and asserts the handler returns 403
Forbidden; reference the mocked symbols isSameOrigin, rateLimit, and
getClientKey and ensure the isSameOrigin mock is reset/restored after the test
so other tests are unaffected.

---

Outside diff comments:
In `@src/app/api/share/`[code]/clone/route.ts:
- Line 2: Consolidate the duplicate imports from "next/server" by importing both
NextRequest and NextResponse in a single statement (replace the separate
NextRequest import with a combined import like import { NextRequest,
NextResponse } from "next/server"); remove the redundant import so only one
import from "next/server" remains and update any references to
NextRequest/NextResponse accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bc34c6f8-a336-46ab-ac71-2e6052f8e2a2

📥 Commits

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

📒 Files selected for processing (12)
  • .jules/sentinel.md
  • src/app/api/lists/[id]/citations/route.test.ts
  • src/app/api/lists/[id]/citations/route.ts
  • src/app/api/lists/route.test.ts
  • src/app/api/lists/route.ts
  • src/app/api/projects/[id]/lists/route.test.ts
  • src/app/api/projects/[id]/lists/route.ts
  • src/app/api/projects/route.test.ts
  • src/app/api/projects/route.ts
  • src/app/api/share/[code]/clone/route.ts
  • src/app/api/share/route.test.ts
  • src/app/api/share/route.ts

Comment on lines +5 to +7
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add test coverage for the CSRF protection.

The mock allows existing tests to pass, but no test verifies that cross-origin POST requests are rejected with 403 Forbidden. The new isSameOrigin guard is a critical security feature and should be tested.

🧪 Proposed test case

Add this test to the POST /api/lists/[id]/citations suite:

+    it("should return 403 for cross-origin requests", async () => {
+      const { isSameOrigin } = await import("`@/lib/security/rate-limit`");
+      const mockIsSameOrigin = isSameOrigin as unknown as ReturnType<typeof vi.fn>;
+      
+      mockAuth.mockResolvedValue({ userId: "user-123" });
+      mockIsSameOrigin.mockReturnValueOnce(false);
+
+      const request = new NextRequest("http://localhost/api/lists/list-123/citations", {
+        method: "POST",
+        body: JSON.stringify({
+          fields: sampleCitationFields,
+          style: "apa",
+          formattedText: "text",
+          formattedHtml: "<p>html</p>",
+        }),
+      });
+      const response = await POST(request, createParams("list-123"));
+      const data = await response.json();
+
+      expect(response.status).toBe(403);
+      expect(data.success).toBe(false);
+      expect(data.error).toBe("Forbidden");
+    });

As per coding guidelines, API routes should have comprehensive test coverage.

🤖 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/lists/`[id]/citations/route.test.ts around lines 5 - 7, Tests
currently mock isSameOrigin to always return true, so there is no coverage that
cross-origin POSTs are rejected; add a test in the POST
/api/lists/[id]/citations suite that temporarily mocks the isSameOrigin guard to
return false (using vi.fn or vi.mock), performs a POST to the route handler, and
asserts the response status is 403 Forbidden and body contains the CSRF error.
Target the isSameOrigin mock from "`@/lib/security/rate-limit`" and update/restore
the mock inside the test so other tests are unaffected.

Comment on lines +5 to +7
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add test coverage for the CSRF protection.

The mock bypasses the origin check, but no test verifies that cross-origin POST requests receive a 403 Forbidden response. The CSRF guard should be tested explicitly.

🧪 Proposed test case

Add this test to the POST /api/lists suite:

+    it("should return 403 for cross-origin requests", async () => {
+      const { isSameOrigin } = await import("`@/lib/security/rate-limit`");
+      const mockIsSameOrigin = isSameOrigin as unknown as ReturnType<typeof vi.fn>;
+      
+      mockAuth.mockResolvedValue({ userId: "user-123" });
+      mockIsSameOrigin.mockReturnValueOnce(false);
+
+      const request = new NextRequest("http://localhost/api/lists", {
+        method: "POST",
+        body: JSON.stringify({ name: "New List" }),
+      });
+
+      const response = await POST(request);
+      const data = await response.json();
+
+      expect(response.status).toBe(403);
+      expect(data.success).toBe(false);
+      expect(data.error).toBe("Forbidden");
+    });

As per coding guidelines, API routes should have comprehensive test coverage.

🤖 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/lists/route.test.ts` around lines 5 - 7, Add a test in
src/app/api/lists/route.test.ts that verifies CSRF protection by making a
cross-origin POST to the POST /api/lists route with isSameOrigin mocked to
return false; specifically, temporarily override the existing vi.mock/vi.fn for
isSameOrigin (or use vi.spyOn) to return false, perform the POST call used by
the suite, and assert the response status is 403 Forbidden; restore/reset the
mock after the test to avoid affecting other tests.

Comment on lines +5 to +7
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add test coverage for the CSRF protection.

The mock allows existing tests to pass without triggering the origin check, but no test confirms that cross-origin POST requests are rejected. This security feature should be tested.

🧪 Proposed test case

Add this test to the POST /api/projects/[id]/lists suite:

+    it("should return 403 for cross-origin requests", async () => {
+      const { isSameOrigin } = await import("`@/lib/security/rate-limit`");
+      const mockIsSameOrigin = isSameOrigin as unknown as ReturnType<typeof vi.fn>;
+      
+      mockAuth.mockResolvedValue({ userId: "user-123" });
+      mockIsSameOrigin.mockReturnValueOnce(false);
+
+      const request = new NextRequest("http://localhost/api/projects/project-123/lists", {
+        method: "POST",
+        body: JSON.stringify({ name: "New List" }),
+      });
+      const response = await POST(request, createParams("project-123"));
+      const data = await response.json();
+
+      expect(response.status).toBe(403);
+      expect(data.success).toBe(false);
+      expect(data.error).toBe("Forbidden");
+    });

As per coding guidelines, API routes should have comprehensive test coverage.

🤖 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/projects/`[id]/lists/route.test.ts around lines 5 - 7, Add a test
in the POST /api/projects/[id]/lists suite in route.test.ts that verifies
CSRF/origin protection by setting the mocked isSameOrigin to return false (use
the same "`@/lib/security/rate-limit`" mock and mutate its isSameOrigin mock to
false), perform a POST to the route under test, and assert the response is
rejected (e.g., status 403 and an error body indicating CSRF/origin failure);
restore or reset the isSameOrigin mock to its original true behavior after the
test so other tests remain unaffected.

Comment on lines +5 to +7
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add test coverage for the CSRF protection.

The mock bypasses the origin validation, but no test verifies that cross-origin POST requests are rejected with 403 Forbidden. The CSRF guard should be tested.

🧪 Proposed test case

Add this test to the POST /api/projects suite:

+    it("should return 403 for cross-origin requests", async () => {
+      const { isSameOrigin } = await import("`@/lib/security/rate-limit`");
+      const mockIsSameOrigin = isSameOrigin as unknown as ReturnType<typeof vi.fn>;
+      
+      mockAuth.mockResolvedValue({ userId: "user-123" });
+      mockIsSameOrigin.mockReturnValueOnce(false);
+
+      const request = new NextRequest("http://localhost/api/projects", {
+        method: "POST",
+        body: JSON.stringify({ name: "New Project" }),
+      });
+
+      const response = await POST(request);
+      const data = await response.json();
+
+      expect(response.status).toBe(403);
+      expect(data.success).toBe(false);
+      expect(data.error).toBe("Forbidden");
+    });

As per coding guidelines, API routes should have comprehensive test coverage.

🤖 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/projects/route.test.ts` around lines 5 - 7, Add a test in
src/app/api/projects/route.test.ts inside the "POST /api/projects" suite that
verifies the CSRF guard rejects cross-origin requests: update or add a mock for
the isSameOrigin function (used in the vi.mock("`@/lib/security/rate-limit`")
setup) to return false for the cross-origin case, perform a POST to the
/api/projects route with a non-same-origin header, and assert the response
status is 403 Forbidden; ensure the test uses the existing test helpers/setup in
the file and restores the original mock behavior after the case so other tests
remain unaffected.

Comment on lines +5 to +9
vi.mock("@/lib/security/rate-limit", () => ({
isSameOrigin: vi.fn(() => true),
rateLimit: vi.fn(() => ({ ok: true })),
getClientKey: vi.fn(),
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add test coverage for the CSRF protection.

The mock bypasses the origin check, but no test verifies that cross-origin POST requests are rejected with 403 Forbidden. This critical security feature should be tested.

🧪 Proposed test case

Add this test to the POST /api/share suite:

+    it("should return 403 for cross-origin requests", async () => {
+      const { isSameOrigin } = await import("`@/lib/security/rate-limit`");
+      const mockIsSameOrigin = isSameOrigin as unknown as ReturnType<typeof vi.fn>;
+      
+      mockAuth.mockResolvedValue({ userId: "user-123" });
+      mockIsSameOrigin.mockReturnValueOnce(false);
+
+      const request = new NextRequest("http://localhost/api/share", {
+        method: "POST",
+        body: JSON.stringify({ type: "list", targetId: "list-123" }),
+      });
+      const response = await POST(request);
+      const data = await response.json();
+
+      expect(response.status).toBe(403);
+      expect(data.success).toBe(false);
+      expect(data.error).toBe("Forbidden");
+    });

As per coding guidelines, API routes should have comprehensive test coverage.

🤖 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/share/route.test.ts` around lines 5 - 9, The test suite currently
mocks isSameOrigin to always return true, so add a test in the POST /api/share
suite that sets the isSameOrigin mock to return false (e.g., vi.mock or
isSameOrigin.mockReturnValueOnce(false)), issues a POST to the /api/share route,
and asserts the handler returns 403 Forbidden; reference the mocked symbols
isSameOrigin, rateLimit, and getClientKey and ensure the isSameOrigin mock is
reset/restored after the test so other tests are unaffected.

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