Skip to main content
Back to Changelog
v2.1.2 · Patch

Security: admin role on every admin route

Two admin routes let any registered user read your subscribers' and customers' emails. If you have a project in production, apply it even if you are not touching anything else.

This release closes a security hole in the boilerplate itself and fixes blog posts with code blocks. If you have a project in production built with CREA.MBA, apply it now.

Admin routes that only asked for a session

GET /api/admin/newsletter and GET /api/admin/subscriptions checked that there was a session, but not that the user was an admin. Any registered user of your app could read the email of every newsletter subscriber and of your customers, with their purchases and subscriptions. They now answer 403.

On top of that, all of api/admin/** now uses a single admin check with consistent answers: 401 without a session, 403 with a session and no admin role. The admin post pages are now protected on the server too, not only in the browser. And a test walks every admin route and fails if a new one does not return 403 to a non-admin: an unguarded endpoint no longer passes bun run test.

Posts with code blocks

Since 2.1.0, any blog post with a code block answered with a 500 error. The syntax highlighter reads the current time while it renders each line, and Next 16 with Cache Components does not allow that. The highlighted output is now cached and those posts load again.

If you already have a project

  1. Copy src/lib/auth/roles.ts and src/lib/auth/admin-guard.ts into your project.
  2. In src/app/api/admin/newsletter/route.ts and src/app/api/admin/subscriptions/route.ts, wrap the GET with withAdmin. If you cannot copy files, the minimal fix is changing if (!session) to if (!session || session.user.role !== 'admin') and returning 403.
  3. Review your own admin routes: grep -rn "getSession" src/app/api/admin.
  4. Copy src/lib/auth/admin-guard.test.ts and run bun run test. It tells you if any admin route is still unguarded.
  5. For posts with code, add 'use cache' and cacheLife('max') at the top of markdownToHtml.
  6. rm -rf .next && bun run build locally before deploying.

No migrations and no new environment variables. The full detail is in the repo's CHANGELOG.md.