
SQLite 3.53.4 CLI - High - Local - Command injection - recover dump emits hostile schema as dot-command
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-cli-recover
Class: Command injection Reach: Local
SQLite 3.53.4 (b09c88c) CLI .recover prints hostile sqlite_schema.sql as a later dot-command. recoverOneStmt prepares only the first statement. A planted CREATE TABLE plus newline .shell is still written. The documented restore pipe runs it as the operator UID.
.dump printSchemaLine is the same emit class. Not libsqlite3. Not --safe. Oracle is echo of a witness string.
| ID | no CVE yet |
| Class | Command injection (CLI .recover / .dump schema emit) |
| Reach | Local (victim runs the documented recover pipe; 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 runs sqlite3 hostile.db .recover | sqlite3 restored.db |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18930 only. Witness SQLITE-CLI-RECOVER-WITNESS. |
Plant a valid first CREATE plus a later .shell in sqlite_schema.sql. A victim who recovers that db into a second sqlite3 runs the dot-command as their UID.
The plant is a .db file. The victim action is the documented recover pipe, not a pasted go line and not --safe off by accident. .shell is system(). The lab oracle is echo of a witness. Not a reverse shell.
Twenty source hunts of 3.53.4. Recover's own hunt called recoverOneStmt a first-statement-only prepare and walked away. The leftover is the print path: recoverSqlCb still emits the extra text. Piping that script is how sqlite.org tells you to restore.
Wrong turns already recorded: treating first-statement prepare as a strip; pinning 3.54.0 (draft); re-filing CVE-2022-46908 --safe; calling this libsqlite3 RCE; using a reverse shell as the oracle.
cd lab
./run.sh
Builds sqlite-src-3530400 into sqlite3 with default Unix CLI recover (OPT_SHELL / SQLITE_ENABLE_DBPAGE_VTAB). writable_schema after .dbconfig defensive off. Planted CREATE TABLE t(x); plus newline .shell echo SQLITE-CLI-RECOVER-WITNESS. .recover printed .shell. Piped into a second sqlite3, it ran. Bind loopback.
SUCCESS sqlite-cli-recover how=recover-pipe-dot-shell recover-has-shell=yes restore-echo=yes SQLITE-CLI-RECOVER-WITNESS
Do not print schema SQL that is not a single statement. Split on the first prepare, emit only that statement, or refuse the row. Quote ordinary CREATE the way virtual-table dump already uses %q. Treat a later . line as hostile and drop it. --safe on the restore sqlite3 blocks .shell; it is not on in the documented pipe.
b09c88c14082339b66c7b7158d609a771e64ca69).recover then restoreext/recover/sqlite3recover.c recoverOneStmt / recoverWriteSchema1src/shell.c.in recoverSqlCb, .dump printSchemaLine