diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..28724f2 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-18 - Prevent SQL Injection via string interpolation in PRAGMA table_info +**Vulnerability:** Found `fmt.Sprintf("PRAGMA table_info(%s);", table)` which uses unsafe string interpolation to inject a table name directly into an SQLite schema query in `sqliteColumnExists`. +**Learning:** PRAGMA statements typically do not support parameterized arguments in many SQLite driver implementations. This led developers to incorrectly fallback to unsafe string interpolation `fmt.Sprintf` for dynamically querying schema information based on variables. +**Prevention:** Use SQLite's safe table-valued function equivalent for pragmas, specifically `pragma_table_info(?)`. This alternative syntax `SELECT ... FROM pragma_table_info(?)` safely accepts parameterized arguments, thereby eliminating SQL injection risks while retrieving schema metadata. Note that columns like `notnull` must be quoted as `"notnull"` because it is a reserved keyword in SQL. diff --git a/internal/storage/sqlite.go b/internal/storage/sqlite.go index 8c0cb1e..1fe82e4 100644 --- a/internal/storage/sqlite.go +++ b/internal/storage/sqlite.go @@ -200,7 +200,7 @@ 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)) + cols, err := db.QueryContext(ctx, "SELECT cid, name, type, \"notnull\", dflt_value, pk FROM pragma_table_info(?);", table) if err != nil { return false, err }