
SQLite 3.53.4 CLI - High - Local - Command injection - go and slash terminators then dot-command
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-cli-go
Class: Command injection Reach: Local
SQLite 3.53.4 (b09c88c) default sqlite3 CLI still treats SQL Server go and Oracle / as statement terminators. line_is_command_terminator rewrites that line to ;. The next line with an empty SQL buffer is do_meta_command, so .shell / .output / .read run as the operator UID.
--safe still blocks .shell. That control holds. Default sqlite3 does not turn --safe on. Not libsqlite3. Oracle is echo of a witness string.
| ID | no CVE yet |
| Class | Command injection (CLI go / / terminator then a later dot-command) |
| Reach | Local (victim runs default sqlite3 on attacker SQL/script without --safe; UI:R) |
| CWE | CWE-78 |
| CVSS | High: 7.8 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Product | SQLite (sqlite3 CLI) |
| Affected | 3.53.4 (b09c88c14082339b66c7b7158d609a771e64ca69) SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc |
| Auth | victim feeds a script to default sqlite3; no --safe |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18920 only. Witness SQLITE-CLI-GO-WITNESS. |
After unterminated SQL in a script the operator feeds to sqlite3 without --safe, a go or / line then .shell / .output / .read runs as the operator UID.
A semicolon already ends a statement. The leftover is terminating SQL that has no ; so a wrapper that thought the statement was still open still runs the next dot-command. .shell is system(). The lab oracle is echo of a witness. Not a reverse shell.
Twenty source hunts of 3.53.4 after OpenLiteSpeed. Latest GA, not the 3.54.0 draft. CLI extras are not the default library. --safe is the documented sink for untrusted scripts (CVE-2022-46908). It still blocks .shell. Default sqlite3 does not turn it on.
src/shell.c.in still has the SQL Server / Oracle compatibility path. Trunk ac6ac0c22d (2026-10-08) disables it unless SQLITE_SHELL_LEGACY_COMMAND_TERMINATOR. That check-in is after this GA.
Wrong turns already recorded: treating a semicolon as the same leftover; re-filing CVE-2022-46908; expecting --safe to be default; calling this libsqlite3 RCE; using a reverse shell as the oracle; pinning 3.54.0 (draft).
cd lab
./run.sh
Builds official sqlite-src-3530400 into default Unix sqlite3 (--disable-readline). Compose sqlite-cli-go. Dummy TCP on 127.0.0.1:18920. Default CLI treated go and / as terminators then ran .shell echo SQLITE-CLI-GO-WITNESS. --safe printed cannot run .shell in safe mode. Bind loopback.
SUCCESS sqlite-cli-go how=go-then-dot-shell slash=yes safe=blocked SQLITE-CLI-GO-WITNESS
Stop treating go and / as terminators, which is what trunk ac6ac0c22d does unless -DSQLITE_SHELL_LEGACY_COMMAND_TERMINATOR. Until then, run untrusted scripts with --safe. --safe is the control that still holds.
b09c88c14082339b66c7b7158d609a771e64ca69)src/shell.c.in line_is_command_terminator, process_input rewrite, do_meta_command, .shell system() after failIfSafeMode--safe--safe