SQLAdmin: Authorization Bypass on `ajax_lookup`
🔗 CVE IDs covered (1)
📋 Description
Impact
The ajax_lookup endpoint in application.py bypasses the is_accessible() access control check that all other endpoints enforce.
If a developer restricts model access by overriding is_accessible(), an authenticated user can still query that model's data through the ajax_lookup endpoint — silently bypassing the restriction.
Affected endpoint:
GET /{identity}/ajax/lookup?name=<field>&term=<query>
All other endpoints enforce both checks:
| Endpoint | @login_required | is_accessible() |
|---|---|---|
| list | ✓ | ✓ |
| create | ✓ | ✓ |
| edit | ✓ | ✓ |
| delete | ✓ | ✓ |
| details | ✓ | ✓ |
| export | ✓ | ✓ |
| ajax_lookup (before fix) | ✗ | ✗ |
| ajax_lookup (after fix) | ✓ | ✓ |
Note: before this fix, ajax_lookup also lacked the @login_required decorator — unauthenticated users could query it directly. That was addressed in #1035. This report covers the remaining gap: authenticated but unauthorized users.
Patches
Two changes were made to ajax_lookup:
- Replaced the hand-rolled authentication check added in #1035 with the standard
@login_requireddecorator used by all other endpoints. - Added the missing
is_accessible(request)check, raisingHTTP 403when it returnsFalse.
Workarounds
None. Developers relying on is_accessible() to restrict model visibility are exposed regardless of what other access controls are in place.
🎯 Affected products1
- pip/sqladmin:<= 0.25.0