fix(admin): prevent SQL injection in system query validation#7748
fix(admin): prevent SQL injection in system query validation#7748fix-it-felix-sentry[bot] wants to merge 3 commits into
Conversation
Added sanitization for SQL queries before using them in EXPLAIN statements to prevent SQL injection vulnerabilities during query validation. Changes: - Added _sanitize_query_for_explain() function to validate and sanitize queries before they are used in EXPLAIN QUERY TREE and EXPLAIN AST statements - Checks for unbalanced quotes, multiple statement attempts, and SQL comments - Applied sanitization in is_query_using_only_system_tables() and is_valid_system_query() functions This fix addresses SQL injection vulnerability in: - snuba/admin/clickhouse/system_queries.py:51 The sanitization adds defense-in-depth protection during the validation phase, while maintaining the existing EXPLAIN AST-based validation logic. Fixes: https://linear.app/getsentry/issue/VULN-1029 Fixes: https://linear.app/getsentry/issue/PF-66 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The unquoted `default` clusterAllReplicas query was incorrectly in the invalid test list. It only appeared to fail before because the old semicolon-stripping logic didn't handle trailing whitespace after the semicolon, causing EXPLAIN to error. The new _sanitize_query_for_explain correctly strips whitespace first, revealing this is a valid query. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve conflict in tests/admin/test_system_queries.py: keep the PR's move of the clusterAllReplicas(default, system.query_log) case into the valid query list, on top of master's switch from @pytest.mark.clickhouse_db to @pytest.mark.events_db. Trim _sanitize_query_for_explain to reduce false positives: drop the fragile unbalanced-quote heuristic (it mishandled ClickHouse '' / \' string escaping) and make string-literal stripping escape-aware before scanning for statement chaining and SQL comments. The EXPLAIN validation runs as the read-only user and the AST checks remain the primary control, so this stays defense-in-depth only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019A8M9WeNTAXuW6rxCjenKJ
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 21ee79f. Configure here.
|
|
||
| # Reject statement chaining outside of string literals. | ||
| if ";" in without_strings: | ||
| raise InvalidCustomQuery("Multiple statements are not allowed") |
There was a problem hiding this comment.
Double trailing semicolon rejected
Low Severity
_sanitize_query_for_explain removes only one trailing semicolon, then treats any remaining ; as multiple statements. Queries that end with more than one semicolon (previously normalized via rstrip(";")) now raise InvalidCustomQuery with a misleading “Multiple statements” message even when the SQL is a single statement.
Reviewed by Cursor Bugbot for commit 21ee79f. Configure here.
|
Closing this without merging. After reviewing the actual code path, this is a true Semgrep finding (raw f-string interpolation of input into a SQL string) but not a practically exploitable SQL injection here, so the added sanitization is low-value defense-in-depth that mainly risks rejecting legitimate queries:
On top of that, the heuristic checks tend to produce false positives on legitimate queries — e.g. ClickHouse If we want defense-in-depth in this path anyway, the better follow-up is to simply keep normalizing the trailing semicolon (as the code already did) without the heuristic rejections. Happy to open that separately if it's wanted. Generated by Claude Code |


Summary
Added sanitization for SQL queries before using them in EXPLAIN statements to prevent SQL injection vulnerabilities during query validation.
Changes
_sanitize_query_for_explain()function to validate and sanitize queries before they are used in EXPLAIN QUERY TREE and EXPLAIN AST statementsis_query_using_only_system_tables()andis_valid_system_query()functionsSecurity Impact
This fix addresses a SQL injection vulnerability where user input was directly interpolated into EXPLAIN statements without proper sanitization. The vulnerability could potentially allow an attacker to:
The fix adds defense-in-depth protection during the validation phase while maintaining the existing EXPLAIN AST-based validation logic.
Testing
The fix maintains backward compatibility with existing legitimate queries:
It properly blocks:
SELECT * FROM ...; DROP TABLE ...)References