Calling const session = await auth() and then immediately proceeding to render data or execute logic without checking if (!session) means the code path runs identically whether the user is authenticated or not. CWE-284 (Improper Access Control) and OWASP A01 apply: a null session is not an error, it's the expected return value when no user is logged in. The absence of a guard after the session call is functionally equivalent to having no auth check at all — the protected logic executes unconditionally.
High because an unguarded session call allows the protected logic to execute when the session is null, bypassing authentication on any route where this pattern appears.
Add a null-check guard within the first few lines after the session call. The guard must redirect or return before any business logic runs.
// Bad: session called but result ignored
const session = await auth()
const users = await prisma.user.findMany() // executes even when session is null
// Good: guard immediately
const session = await auth()
if (!session?.user) {
redirect('/login')
// or for API routes:
// return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
const users = await prisma.user.findMany()
The pattern if (!session?.user) redirect('/login') is idiomatic for Next.js App Router server components. For API routes, use an early return Response.json(...) with status 401.
ID: ai-slop-security-theater.unbound-auth.session-getter-failures-return-early
Severity: high
What to look for: For each file that calls a session getter, find the call and check the next 5 lines of source code below the call. Count all session-getter call sites and verify at least 1 of these guard patterns appears within those 5 lines: if (!session) return, if (!session?.user) return, if (!user) return, if (!session) throw, if (!user) throw, if (!session) redirect(, if (!user) redirect(, if (!session) notFound(), if (session === null) .... Count all files where the session getter is called but no guard follows it.
Pass criteria: 100% of files calling a session getter have a null-check guard within 5 lines after the call. Report: "X session-getter call sites, Y guarded immediately, 0 unguarded."
Fail criteria: At least 1 session-getter call has no guard pattern within 5 lines below it — the protected logic runs even when the session is null.
Skip (N/A) when: No file in the project calls a session getter function.
Detail on fail: "1 unguarded session call: app/admin/page.tsx line 12 calls await auth() but never checks the result before rendering admin data on line 15"
Remediation: Call the session getter and immediately check the result. Don't trust that the session "must be present":
// Bad: session call without guard
const session = await auth()
const users = await prisma.user.findMany() // runs even if session is null
// Good: guard immediately after the call
const session = await auth()
if (!session?.user) {
redirect('/login') // or return Response.json({...}, { status: 401 })
}
const users = await prisma.user.findMany()