{"id":"PYSEC-2026-3922","summary":"SQLAdmin: Unvalidated sortBy parameter in `ModelView` bypasses `column_sortable_list`","details":"## Summary\n\n`ModelView.sort_query()` uses the attacker-controlled `sortBy` list-view query parameter without checking it against the configured `column_sortable_list` allow-list. The value is resolved with `getattr(model, ...)` and fed into relationship joins and `order_by()`, so a request can sort by **any** column of the model — including ones hidden from `column_list` — and, via a dotted path, by columns of related models. Because row order then reflects the value of an unexposed column, this is an information-exposure **ordering oracle**.\n\n## Root cause\n\n`column_sortable_list` is consulted only in the list template to decide which header links to render; the server never enforces it, so removing a column from the UI does not prevent sorting by it.\n\n## Exploitation\n\nA single request leaks the relative ordering of an unexposed column; the `asc`↔`desc` reversal confirms rows are ordered by the secret's actual value. Pairing `sortBy` with searchable/filterable columns and pagination can narrow the oracle toward specific values, though value recovery is conditional on having a filterable target column.","aliases":["CVE-2026-54529","GHSA-ccg5-9c8w-xh6v"],"modified":"2026-09-10T12:15:11.750066922Z","published":"2026-09-10T09:45:01.332936Z","references":[{"type":"WEB","url":"https://github.com/smithyhq/sqladmin/security/advisories/GHSA-ccg5-9c8w-xh6v"},{"type":"PACKAGE","url":"https://github.com/smithyhq/sqladmin"},{"type":"WEB","url":"https://github.com/smithyhq/sqladmin/releases/tag/0.27.1"},{"type":"PACKAGE","url":"https://pypi.org/project/sqladmin"},{"type":"ADVISORY","url":"https://github.com/advisories/GHSA-ccg5-9c8w-xh6v"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-54529"}],"affected":[{"package":{"name":"sqladmin","ecosystem":"PyPI","purl":"pkg:pypi/sqladmin"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.27.1"}]}],"versions":["0.0.0","0.1.0","0.1.1","0.1.10","0.1.11","0.1.12","0.1.2","0.1.3","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.9","0.10.0","0.10.1","0.10.2","0.10.3","0.11.0","0.12.0","0.13.0","0.14.0","0.14.1","0.15.0","0.15.1","0.15.2","0.16.0","0.16.1","0.17.0","0.18.0","0.19.0","0.2.0","0.2.1","0.20.0","0.20.1","0.21.0","0.22.0","0.23.0","0.24.0","0.25.0","0.25.1","0.26.0","0.27.0","0.3.0","0.4.0","0.5.0","0.6.0","0.6.1","0.7.0","0.8.0","0.9.0"],"database_specific":{"source":"https://github.com/pypa/advisory-database/blob/main/vulns/sqladmin/PYSEC-2026-3922.yaml"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N"}]}