flawopen.com/SQL Injection in Go/GORM Raw SQL and SQL injection
Is GORM Raw() Safe from SQL Injection? Parameter Binding in Go
Think of a placeholder as a sealed envelope for a value: the database driver sends the value separately from the SQL instructions. GORM Raw() can bind safely when you keep the placeholder in the query and pass the value as an argument. Formatting user input into the SQL string mixes the envelope with the instructions and can change the query.
// User-controlled text becomes SQL syntax db.Raw(fmt.Sprintf( "SELECT * FROM users WHERE id = %s", userID, )).Scan(&user)
// The driver binds userID as a value db.Raw( "SELECT * FROM users WHERE id = ?", userID, ).Scan(&user)
Safe GORM Raw SQL and parameter binding
GORM and Go's database/sql bind values when placeholders stay in the SQL and arguments are passed separately, for example db.Where("name = ?", userInput) or db.Raw("SELECT ... WHERE id = ?", userID). A placeholder represents a value, not SQL syntax: table names, column names, sort directions, and operators cannot be made safe by binding them as values. Select dynamic identifiers from a fixed allowlist. Methods such as Order, Select, Table, and Raw can be injectable when user input is concatenated into their SQL fragments.
- ✓Keep SQL structure fixed and pass user values through separate placeholders and arguments.
- ✓Choose dynamic table names, column names, and sort directions from fixed application-owned allowlists.
- ✓Review raw-fragment methods such as
Raw,Exec,Order,Select, andTablefor concatenation or formatting. - ✓Parse numeric identifiers into their expected Go type and handle conversion errors before querying.
How to check your codebase
rg -n --glob '*.go' '\.(Raw|Exec|Order|Select|Table)\s*\(' .
rg -n --glob '*.go' 'fmt\.(Sprintf|Sprint)' .GORM Raw SQL and parameter binding FAQ
No. Conditions that pass values separately, such as Where("name = ?", input), use parameter binding. Concatenating input into a condition string or passing it as raw SQL syntax can still inject a query. Some methods accept identifiers or SQL fragments that are not escaped; inspect their arguments and allowlist dynamic structure.
No. Placeholders represent data values. For a dynamic identifier or sort direction, choose from fixed application-defined options and insert only that validated constant into the SQL structure.
References
- GORM docs — SQL Injection Methods
- GORM docs — Raw SQL and parameterized queries
- flawopen.com — SQL Injection in Go