GuardAPI

Fix BOLA (Broken Object Level Authorization) in Bottle

BOLA (Broken Object Level Authorization), formerly IDOR, is the most prevalent vulnerability in modern APIs. In the Bottle framework, BOLA occurs when a route handler uses a user-supplied identifier to access a database object without validating if the authenticated user has the rights to that specific object. Attackers simply iterate through IDs to scrape private data. To kill BOLA, you must enforce authorization at the object level, not just the endpoint level.

The Vulnerable Pattern

@route('/api/reports/')
def get_report(report_id):
    # VULNERABLE: Trusting the report_id without checking ownership
    report = db.execute('SELECT * FROM reports WHERE id=?', (report_id,)).fetchone()
    if not report:
        abort(404, 'Report not found')
    return {'data': report['content']}

The Secure Implementation

The fix involves two critical steps: 1) Identify the requester using a secure session or verified JWT (never trust a user_id passed in the body or URL). 2) Update your database queries to include the owner's ID in the WHERE clause. If a user tries to access a report_id they don't own, the query returns null, and the application responds with a 404 or 403, effectively neutralizing the unauthorized access attempt.

@route('/api/reports/')
def get_report(report_id):
    # SECURE: Bind the resource lookup to the authenticated user_id
    user_id = request.environ.get('auth_user_id') 
    report = db.execute('SELECT * FROM reports WHERE id=? AND owner_id=?', (report_id, user_id)).fetchone()
if not report:
    # Use 403 or 404 to prevent ID enumeration
    abort(404, 'Report not found')

return {'data': report['content']}</code></pre>

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]