From 20c70f10693c6d8792c623ca054c13a90c1db4d1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 11:57:41 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[CRITICAL]?= =?UTF-8?q?=20Fix=20SQL=20injection=20in=20schema=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🚨 Severity: CRITICAL 💡 Vulnerability: SQL injection vulnerability in internal database schema validation. 🎯 Impact: Untrusted table names could be dynamically interpolated into PRAGMA queries. 🔧 Fix: Used SQLite's parameterized table-valued function `pragma_table_info(?)` instead of string interpolation `PRAGMA table_info(%s)`. ✅ Verification: Ran testing via `go test ./internal/storage/...` and recorded to Sentinel journal. Co-authored-by: mattjoyce <278869+mattjoyce@users.noreply.github.com> --- .jules/sentinel.md | 4 ++++ internal/storage/sqlite.go | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 00000000..00771bec --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2025-02-21 - Fix SQL injection in SQLite schema validation +**Vulnerability:** SQL injection in `internal/storage/sqlite.go` due to using `fmt.Sprintf` to concatenate the table name into `PRAGMA table_info(%s);` when checking if a schema column exists. +**Learning:** Even internal toolings or internal schema validation queries against SQLite need strict parameters. While `PRAGMA` statements typically do not support parameterized variables, the table-valued function `pragma_table_info(?)` does, providing a secure alternative for metadata extraction. +**Prevention:** Avoid string formatting to construct SQL queries, especially for tables or object names. When retrieving metadata in SQLite, prefer parameterized PRAGMA functions like `SELECT * FROM pragma_table_info(?)` over direct string interpolation. diff --git a/internal/storage/sqlite.go b/internal/storage/sqlite.go index 8c0cb1ed..130921fd 100644 --- a/internal/storage/sqlite.go +++ b/internal/storage/sqlite.go @@ -200,7 +200,8 @@ LIMIT 1; } func sqliteColumnExists(ctx context.Context, db *sql.DB, table, column string) (bool, error) { - cols, err := db.QueryContext(ctx, fmt.Sprintf("PRAGMA table_info(%s);", table)) + // Use table-valued function to avoid SQL injection on table name + cols, err := db.QueryContext(ctx, `SELECT cid, name, type, "notnull", dflt_value, pk FROM pragma_table_info(?)`, table) if err != nil { return false, err }