GuardAPI

Fix BOLA (Broken Object Level Authorization) in NestJS

Generated remediation sketch. GuardAPI the product only gates GET BOLA in CI.

BOLA (Broken Object Level Authorization) is the #1 API threat. In NestJS, it occurs when you trust a route parameter like :id without verifying if the authenticated user (req.user) actually owns that resource. If your service just does findOne(id), you're wide open for horizontal privilege escalation.

The Vulnerable Pattern

@Get(':id')
@UseGuards(JwtAuthGuard)
async getInvoice(@Param('id') id: string) {
  // VULNERABILITY: Any authenticated user can fetch any invoice ID.
  // No check to see if the invoice belongs to the user.
  return this.invoiceService.findOne(id);
}

The Secure Implementation

To kill BOLA in NestJS, you must enforce ownership at the database query level or via a custom Guard/Interceptor. 1. Never trust the ID in the URL. 2. Always extract the requester's identity from the JWT/Session. 3. Scope your SQL/NoSQL queries so they include the owner identifier (e.g., WHERE id = :id AND user_id = :current_user). 4. For complex logic, implement a 'PolicyGuard' or 'CaslAbility' to evaluate permissions before the controller logic executes.

@Get(':id')
@UseGuards(JwtAuthGuard)
async getInvoice(@Param('id') id: string, @Req() req) {
  const userId = req.user.id;
  const invoice = await this.invoiceService.findOne(id);

// SECURE: Explicit ownership check if (!invoice || invoice.ownerId !== userId) { throw new ForbiddenException(‘You do not have access to this resource’); }

return invoice; }

// ALTERNATIVE (Scoped Query): // return this.invoiceService.findOne({ where: { id, ownerId: userId } });

Prove it on the next pull request

This page is a generated code sketch, not a GuardAPI scan. After you scope the query by tenant, fail the GitHub job when tenant B can still GET tenant A's object. GET-only. Tokens stay in GitHub Secrets.

- uses: GuardAPI/ghost-api@v6
  with:
    api-key: ${{ secrets.GUARD_API_KEY }}
    openapi-path: ./openapi.json
    base-url: ${{ secrets.STAGING_API_URL }}
    token-a: ${{ secrets.TOKEN_USER_A }}
    token-b: ${{ secrets.TOKEN_USER_B }}

Install docs · 14-day trial · How the fail rule works

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