GuardAPI

Fix BOLA (Broken Object Level Authorization) in Blitz.js

BOLA (Broken Object Level Authorization) is the primary attack vector in Blitz.js applications. It occurs when an endpoint accepts an object identifier (like a UUID or numeric ID) and retrieves data without verifying if the requester owns that resource. In Blitz's RPC-like architecture, this usually manifests in queries and mutations that trust the client-provided ID blindly.

The Vulnerable Pattern

import { resolver } from 'blitz';
import db from 'db';
import { z } from 'zod';

const GetProject = z.object({ id: z.number() });

export default resolver.pipe( resolver.zod(GetProject), resolver.authorize(), async ({ id }) => { // VULNERABLE: Any logged-in user can fetch any project by ID. const project = await db.project.findFirst({ where: { id } }); return project; } );

The Secure Implementation

To fix BOLA in Blitz.js, you must enforce ownership at the database layer. The vulnerable code only checks if the user is logged in (resolver.authorize()), but allows them to query any ID. The secure implementation uses the 'ctx.session' object—which is populated server-side and cannot be tampered with by the client—to scope the Prisma 'where' clause. By adding 'userId: ctx.session.userId' to the query, the database will only return the record if it belongs to the authenticated user. If the record exists but belongs to someone else, the query returns null, and we throw a NotFoundError to avoid leaking the existence of the resource.

import { resolver, NotFoundError } from 'blitz';
import db from 'db';
import { z } from 'zod';

const GetProject = z.object({ id: z.number() });

export default resolver.pipe( resolver.zod(GetProject), resolver.authorize(), async ({ id }, ctx) => { // SECURE: Query is scoped to the session’s userId. const project = await db.project.findFirst({ where: { id, userId: ctx.session.userId }, });

if (!project) throw new NotFoundError();
return project;

} );

About this page

Framework notes in /guides are generated sketches kept for URL stability. They are not human pentest reports and they are not GuardAPI scan output. The product is a GET-only BOLA merge gate. Maintained by GuardAPI. Questions: [email protected]