Pre-Launch Scan
Prepared for Clearpath Ops · April 14, 2026 · CONFIDENTIAL
- src/api/
- src/auth/
- src/db/
- .env.example
- prisma/schema.prisma
- Frontend UI
- Mobile client
- Third-party integrations
Stack: Next.js 14, Prisma ORM, Supabase (Postgres), Stripe. Clearpath Ops processes employee PTO requests and payroll adjustment approvals — the application handles real employee names, employment status, and manager hierarchies.
The GET and PATCH handlers for /api/pto/[id] verify that a request is authenticated but do not verify that the requesting user is the record owner or the record's assigned manager. Any employee who knows or guesses a PTO record ID can view or approve it.
Any employee could view or modify any other employee's PTO records, including approval status and attached manager notes. This would constitute unauthorized access to HR records on day one of the product's life.
Add a scope check — if (record.employeeId !== session.userId && record.managerId !== session.userId) — before returning or mutating the record. The correct session shape is already available at this call site.
SUPABASE_SERVICE_ROLE_KEY is imported in a file that Next.js includes in the client bundle. The file at src/lib/supabase.ts is not marked server-only. The service role key bypasses all Row Level Security — anyone who loads the app can extract this key from the browser and interact with the database directly.
Exposure of the service role key would grant any visitor full read/write access to the entire Supabase database, bypassing all RLS policies. This is an immediate data breach vector on launch day.
Move all service role usage to src/lib/supabase.server.ts, add 'server-only' import guard at the top of the file, and rotate the key in the Supabase console before going live.
-
01Fix CRITICAL-01: add ownership scope check to all PTO record handlersEst. 2–3 hrs
-
02Fix CRITICAL-02: move service role to server-only file, add import guardEst. 1–2 hrs
-
03Rotate the Supabase service role key in the Supabase console5 min
-
04Redeploy and smoke-test both endpoints before going live. Confirm the service role key is absent from the browser network tab.30 min
-
05Consider a Standard Audit post-launch. This scan covered only the highest-risk paths — a full codebase review would surface medium and low findings that were out of scope here.Future
The following items were observed but do not block launch. They should be addressed in the first post-launch sprint.
- JWT expiration is set to 30 days. Industry standard for internal HR tools is 8–24 hours. Reduce before handling sensitive payroll data.
- No rate limiting on /api/auth/login. Low-risk pre-launch with a small user base, but implement before scaling.