Skip to content

fix: security review by claude#998

Open
MasterIceZ wants to merge 2 commits into
mainfrom
fix/security-scans
Open

fix: security review by claude#998
MasterIceZ wants to merge 2 commits into
mainfrom
fix/security-scans

Conversation

@MasterIceZ

@MasterIceZ MasterIceZ commented Jun 14, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Bug Fixes

    • Updated the render flow to stop processing when the API request fails, avoiding incorrect UI updates.
  • Chores

    • Enhanced security by adding security-focused HTTP headers across all routes.
    • Strengthened API authorization checks so only authorized users can access/operate on protected resources.
    • Improved validation for task file paths with stricter pattern constraints.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c63dc199-e70a-488d-b486-7134581cd6f7

📥 Commits

Reviewing files that changed from the base of the PR and between d6ceffd and 1b3ad5a.

📒 Files selected for processing (1)
  • next.config.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • next.config.mjs

📝 Walkthrough

Walkthrough

Adds HTTP security headers (CSP, X-Frame-Options, etc.) to the Next.js config for all routes. Enforces authentication on /api/render POST, restricts /api/assessments POST and /api/users GET to admin-only. Adds submission ownership authorization on the realtime route with userId payload sanitization. Tightens FilePath Zod validation, adds a client-side res.ok guard on the render page, and removes a debug console.log.

Changes

Security Hardening and Access Control

Layer / File(s) Summary
Global HTTP security headers
next.config.mjs
Adds async headers() to the Next.js config that applies X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and a dynamically built Content-Security-Policy to all routes.
Authentication and admin-only authorization on API routes
src/app/api/render/route.ts, src/app/api/assessments/route.ts, src/app/api/users/route.ts, src/app/api/tasks/[id]/route.ts
Adds getServerUser + unauthorized() guard to render POST; restricts assessments POST to admins via forbidden(); changes users GET from owner-or-admin to admin-only by removing checkOwnerPermission; removes debug console.log from tasks DELETE.
Submission ownership check and payload sanitization
src/app/api/submissions/[id]/realtime/route.ts
Adds userId to the Prisma select, gates private-task access by comparing submission.userId with the requester's id, and strips userId from the JSON response payload.
FilePath schema validation and render page error guard
src/lib/api/schema/tasks.ts, src/app/render/page.tsx
Rewrites FilePath Zod schema to validate path with a non-empty regex constraint; adds a res.ok early-return guard in the render page to prevent parsing error responses as JSON.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant RenderPOST as /api/render POST
  participant AssessmentsPOST as /api/assessments POST
  participant UsersGET as /api/users GET
  participant RealtimeGET as /api/submissions/[id]/realtime GET
  participant getServerUser
  participant Prisma

  rect rgba(100, 150, 255, 0.5)
    note over RenderPOST,UsersGET: Core API auth guards
    Client->>RenderPOST: POST /api/render {content}
    RenderPOST->>getServerUser: getServerUser()
    getServerUser-->>RenderPOST: user | null
    alt no user
      RenderPOST-->>Client: 401 unauthorized()
    else authenticated
      RenderPOST-->>Client: 200 json(html)
    end
  end

  rect rgba(150, 100, 255, 0.5)
    note over AssessmentsPOST,UsersGET: Admin-only endpoints
    Client->>AssessmentsPOST: POST /api/assessments
    AssessmentsPOST->>getServerUser: getServerUser()
    getServerUser-->>AssessmentsPOST: user
    alt user.admin false
      AssessmentsPOST-->>Client: 403 forbidden()
    else admin user
      AssessmentsPOST-->>Client: 200 json(assessment)
    end

    Client->>UsersGET: GET /api/users
    UsersGET->>getServerUser: getServerUser()
    getServerUser-->>UsersGET: user
    alt user.admin false
      UsersGET-->>Client: 403 forbidden()
    else admin user
      UsersGET-->>Client: 200 json(users)
    end
  end

  rect rgba(100, 255, 150, 0.5)
    note over RealtimeGET,Prisma: Submission ownership gate
    Client->>RealtimeGET: GET /api/submissions/[id]/realtime
    RealtimeGET->>Prisma: findUnique({select: {userId, task, ...}})
    Prisma-->>RealtimeGET: submission
    alt task.private && !admin && userId !== user.id
      RealtimeGET-->>Client: 403 forbidden()
    else authorized
      RealtimeGET->>RealtimeGET: delete payload.task, payload.userId
      RealtimeGET-->>Client: 200 json(sanitized)
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop hop, the gates are sealed tight,
No sneaky requests get past tonight!
CSP headers line the burrow wall,
Admin checks stand strong and tall.
userId scrubbed from every reply—
This bunny keeps your secrets dry! 🔒

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'fix: security review by claude' is vague and generic. It mentions 'security review' but does not clearly describe the specific security improvements being made across the codebase. Consider using a more descriptive title that specifies the main security changes, such as 'fix: add security headers and strengthen API authorization checks' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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 fix/security-scans

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 1.31% 135 / 10247
🔵 Statements 1.31% 135 / 10247
🔵 Functions 48.81% 103 / 211
🔵 Branches 51.78% 116 / 224
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
next.config.mjs 0% 0% 0% 0% 1-43
src/app/api/assessments/route.ts 0% 100% 100% 0% 3-93
src/app/api/render/route.ts 0% 100% 100% 0% 3-21
src/app/api/submissions/[id]/realtime/route.ts 0% 0% 0% 0% 1-59
src/app/api/tasks/[id]/route.ts 0% 0% 0% 0% 1-169
src/app/api/users/route.ts 0% 0% 0% 0% 1-26
src/app/render/page.tsx 0% 100% 100% 0% 3-62
src/lib/api/schema/tasks.ts 0% 0% 0% 0% 1-28
Generated in workflow #2607 for commit 1b3ad5a by the Vitest Coverage Report Action

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
src/app/render/page.tsx (1)

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

Handle thrown fetch errors so loading state is always reset.

On Line 19, fetch can throw (network/abort), and the current res.ok branch won’t run. Wrap this block in try/finally so setLoading(false) is guaranteed.

Suggested fix
   async function render() {
-    setLoading(true)
-    const res = await fetch('/api/render', {
-      method: 'POST',
-      body: JSON.stringify({ content: md })
-    })
-    if (!res.ok) {
-      setLoading(false)
-      return
-    }
-    setRendered(await res.json())
-    setLoading(false)
+    setLoading(true)
+    try {
+      const res = await fetch('/api/render', {
+        method: 'POST',
+        body: JSON.stringify({ content: md })
+      })
+      if (!res.ok) return
+      setRendered(await res.json())
+    } finally {
+      setLoading(false)
+    }
   }
🤖 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/render/page.tsx` around lines 19 - 29, The fetch call on line 19 can
throw errors due to network issues or request abortion, and when it does, the
setLoading(false) statement never executes, leaving the loading state
permanently true. Wrap the entire fetch block (from the fetch call through the
setRendered and setLoading calls) in a try/finally statement, moving the
setLoading(false) call into the finally block to guarantee it always executes
regardless of whether fetch throws or returns a response.
🤖 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 `@next.config.mjs`:
- Around line 30-33: Remove the 'unsafe-eval' directive from the script-src
policy in the CSP header array. Locate the line containing "script-src 'self'
'unsafe-inline' 'unsafe-eval'" in next.config.mjs and remove 'unsafe-eval' from
the string, keeping only 'self' and 'unsafe-inline' to maintain necessary
functionality while improving XSS protection.

---

Outside diff comments:
In `@src/app/render/page.tsx`:
- Around line 19-29: The fetch call on line 19 can throw errors due to network
issues or request abortion, and when it does, the setLoading(false) statement
never executes, leaving the loading state permanently true. Wrap the entire
fetch block (from the fetch call through the setRendered and setLoading calls)
in a try/finally statement, moving the setLoading(false) call into the finally
block to guarantee it always executes regardless of whether fetch throws or
returns a response.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 10c5f75b-d0b6-4b63-b90c-392bb0263646

📥 Commits

Reviewing files that changed from the base of the PR and between 79962f2 and d6ceffd.

📒 Files selected for processing (8)
  • next.config.mjs
  • src/app/api/assessments/route.ts
  • src/app/api/render/route.ts
  • src/app/api/submissions/[id]/realtime/route.ts
  • src/app/api/tasks/[id]/route.ts
  • src/app/api/users/route.ts
  • src/app/render/page.tsx
  • src/lib/api/schema/tasks.ts
💤 Files with no reviewable changes (1)
  • src/app/api/tasks/[id]/route.ts

Comment thread next.config.mjs
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.

1 participant