mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-08-10 08:21:54 +00:00
NL2SQLTool's read-only mode could be bypassed three ways, all confirmed by executing the validators directly. 1. `_AS_PAREN_RE` was `\bAS\s*\(`, which never matches PostgreSQL's `AS [NOT] MATERIALIZED (`. `WITH d AS MATERIALIZED (DELETE FROM users RETURNING *) SELECT * FROM d` therefore parsed as having no CTE body at all, and `_validate_statement` returned without running a single check. 2. `_resolve_explain_command` scanned raw text, so a comment between the keywords (`EXPLAIN /*x*/ ANALYZE DELETE FROM users`) stalled option parsing and the statement was treated as an inert EXPLAIN. EXPLAIN ANALYZE executes its argument. 3. The first-keyword allowlist admits statements that begin with SELECT but write, and those survive a transaction rollback: MySQL `SELECT ... INTO OUTFILE` writes a file on the DB server, and `pg_read_file` / `lo_import` / `dblink_exec` reach its filesystem or open a connection outside the transaction. Changes: - Analyse statements over a mask that blanks string literals, dollar-quoted strings, quoted identifiers and comments while preserving offsets, so a keyword in a literal is never matched and one behind a comment always is. MySQL executable comments (`/*! ... */`) are left visible because the server runs them. - Match the `AS [NOT] MATERIALIZED (` spelling. - Validate CTE bodies against an allowlist of read-only leading keywords instead of a write-command denylist, and fail closed: a WITH statement whose CTE bodies cannot be located, or which has no query after them, is now rejected rather than passed through. - Block INTO OUTFILE/DUMPFILE and known server-filesystem functions. - Mark the transaction `SET TRANSACTION READ ONLY` in read-only mode where the backend supports it, so enforcement no longer rests on parsing alone. Backends without the syntax log and fall back. - Split statements on semicolons outside strings and comments, which also stops a semicolon in a literal from being rejected as multi-statement. - Document that a least-privileged read-only DB role is the actual control and these checks are defence in depth. Adds 30 regression tests. Full file: 111 passed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
30 KiB
30 KiB