GuardAPI

Fix BOLA (Broken Object Level Authorization) in Astro

BOLA (formerly IDOR) is the apex predator of API vulnerabilities. In Astro's SSR and API routes, it occurs when you trust the 'id' parameter provided by the client without verifying if the authenticated user has the rights to access that specific resource. If you're querying your DB using only a user-supplied ID, you're wide open to horizontal privilege escalation.

The Vulnerable Pattern

import { db, Posts, eq } from 'astro:db';

export const GET: APIRoute = async ({ params }) => { const { id } = params; // VULNERABILITY: Blindly trusting the ‘id’ from the URL. // Any logged-in (or anonymous) user can crawl this endpoint by incrementing IDs. const post = await db.select().from(Posts).where(eq(Posts.id, id)).get();

if (!post) return new Response(null, { status: 404 }); return new Response(JSON.stringify(post)); };

The Secure Implementation

The fix shifts the authorization logic from the 'perimeter' to the 'data layer'. Instead of just checking if a user is logged in, we enforce ownership within the SQL query itself. By using `and(eq(Posts.id, id), eq(Posts.authorId, user.id))`, the database will only return a result if the record belongs to the requester. If the record exists but belongs to someone else, the query returns null, and we issue a 404. This pattern effectively kills BOLA by making object-level access dependent on the session identity, not just the URL structure.

import { db, Posts, eq, and } from 'astro:db';

export const GET: APIRoute = async ({ params, locals }) => { const { id } = params; const user = locals.user; // Populated by your auth middleware (e.g., Lucia, Auth.js)

if (!user) { return new Response(‘Unauthorized’, { status: 401 }); }

// FIX: Scope the query to BOTH the object ID and the authenticated User ID. // This ensures a user can only retrieve records they actually own. const post = await db.select() .from(Posts) .where( and( eq(Posts.id, id), eq(Posts.authorId, user.id) ) ).get();

if (!post) { // Return 404 instead of 403 to prevent ID enumeration/probing. return new Response(‘Not Found’, { status: 404 }); }

return new Response(JSON.stringify(post)); };

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: support@guard-api.com