fix build error - #25
Conversation
Greptile SummaryThis PR fixes a Next.js 15 build error by splitting the dev-access page into a Server Component ( One security issue was found:
Confidence Score: 4/5Safe to merge after fixing the open-redirect guard in getNextPath The refactor is correct and necessary for Next.js 15 compatibility, but the open-redirect vulnerability in getNextPath is a real security defect that should be resolved before this ships to production frontend/app/dev-access/page.tsx — specifically the getNextPath validation on line 11 Important Files Changed
Sequence DiagramsequenceDiagram
participant Browser
participant DevAccessPage as DevAccessPage (Server)
participant DevAccessForm as DevAccessForm (Client)
participant API as Backend API
Browser->>DevAccessPage: GET /dev-access?next=/dashboard
DevAccessPage->>DevAccessPage: await searchParams
DevAccessPage->>DevAccessPage: getNextPath(next) → "/dashboard"
DevAccessPage->>Browser: Render DevAccessForm nextPath="/dashboard"
Browser->>DevAccessForm: User submits password
DevAccessForm->>API: POST /api/access-gate/unlock { password }
alt Success
API-->>DevAccessForm: 200 OK (sets httpOnly cookie)
DevAccessForm->>Browser: window.location.assign("/dashboard")
else Failure
API-->>DevAccessForm: 4xx { detail: "..." }
DevAccessForm->>Browser: Show error message
end
Reviews (1): Last reviewed commit: "fix build error" | Re-trigger Greptile |
| </div> | ||
| function getNextPath(rawValue: string | string[] | undefined): string { | ||
| const value = Array.isArray(rawValue) ? rawValue[0] : rawValue; | ||
| return value?.startsWith('/') ? value : '/'; |
There was a problem hiding this comment.
Open redirect via protocol-relative URL
value.startsWith('/') also returns true for //evil.com. When window.location.assign('//evil.com') is called, browsers treat // as a protocol-relative URL and navigate to https://evil.com, allowing an attacker to craft a link like /dev-access?next=//evil.com that redirects the user to an external site after they authenticate.
Fix by additionally rejecting paths that start with //:
| return value?.startsWith('/') ? value : '/'; | |
| return value?.startsWith('/') && !value.startsWith('//') ? value : '/'; |
No description provided.