[Senate] Fix SQL injection patterns in cli.py and api.py

← All Specs

[Senate] Fix SQL injection patterns in cli.py and api.py

ID: 9b9a9320-d85 Priority: 89 Type: one_shot Status: open

Goal

Critical (C-1, C-2): SQL injection via f-strings in cli.py:212 (dynamic table names) and api.py:2872 (unused placeholders variable). Add table name allowlist validation in cli.py. Remove unused placeholders in api.py. Validate entity_name before queries. See security_audit_2026-04-02.md.

Acceptance Criteria

☑ Concrete deliverables created
☑ Work log updated with timestamped entry

Work Log

2026-04-26

C-1 (cli.py): Promoted valid_tables local list to module-level _ALLOWED_DB_TABLES frozenset constant. Changed cmd_db stats to iterate over the constant and added an explicit if table not in _ALLOWED_DB_TABLES: continue validation guard as the audit recommends. Changed bare except: to except Exception:.

C-2 (api.py): Found the original unused-placeholders pattern at api.py:43113 (code heavily restructured since audit). The query at that location used SQLite ? syntax (broken in PostgreSQL), had a no-op .replace('%s', '%s' * 1), and the placeholders variable it created was never referenced in the query body. Fixed by removing placeholders, building proper per-gene LIKE clauses via gene_clauses, and using fully parameterized PostgreSQL %s bindings.

entity_name validation: Already in place at entity_detail (line 57535) and api_entity_detail (line 15289) — both validate with re.match(r"^[A-Za-z0-9_\- .,'/&()^+]+$", entity_name) and return 404 for invalid formats. No further changes needed.

Tasks using this spec (1)
[Senate] Fix SQL injection patterns in cli.py and api.py
Senate done P89
File: 9b9a9320_d85_spec.md
Modified: 2026-04-25 23:40
Size: 1.6 KB