Fix BOLA (Broken Object Level Authorization) in Django
Generated remediation sketch. GuardAPI the product only gates GET BOLA in CI.
BOLA (formerly IDOR) remains the #1 threat in the OWASP API Top 10. It occurs when an application relies on user-supplied IDs to access objects without validating ownership. In Django, this typically manifests when developers fetch an object directly from the model manager using a primary key from the URL, assuming that authentication equals authorization.
The Vulnerable Pattern
from django.http import JsonResponse from .models import InvoiceVULNERABLE: Any authenticated user can guess an ID and access any invoice
def get_invoice(request, invoice_id): invoice = Invoice.objects.get(id=invoice_id) return JsonResponse({‘id’: invoice.id, ‘amount’: invoice.amount, ‘secret_note’: invoice.secret_note})
The Secure Implementation
The fix involves enforcing 'Ownership-Based Access Control' at the database layer. Instead of querying the entire table, you must scope the queryset to the current 'request.user'. By using 'get_object_or_404(Model, id=id, owner=request.user)', the ORM generates a SQL query with a WHERE clause that includes both the ID and the owner_id. If a user tries to access an ID they don't own, the database returns no record, and Django correctly triggers a 404 Not Found, preventing data leakage. For Django Rest Framework (DRF), always override 'get_queryset()' to return 'self.request.user.invoices.all()' instead of 'Invoice.objects.all()'.
from django.shortcuts import get_object_or_404 from django.http import JsonResponse from .models import InvoiceSECURE: Query is scoped strictly to the requesting user
def get_invoice(request, invoice_id): invoice = get_object_or_404(Invoice, id=invoice_id, owner=request.user) return JsonResponse({‘id’: invoice.id, ‘amount’: invoice.amount, ‘secret_note’: invoice.secret_note})
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 }}
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