Jomel.Tr
Web Vulnerabilities — Go
Direct concatenation of user input into a SQL query.
vulnerable.go
func GetUser(db *sql.DB, id string) (*User, error) {
// id может быть: 1 OR 1=1 --
query := "SELECT * FROM users WHERE id = " + id
row := db.QueryRow(query)
var u User
err := row.Scan(&u.ID, &u.Name, &u.Email)
return &u, err
} secure.go
func GetUser(db *sql.DB, id string) (*User, error) {
// Параметризованный запрос — id всегда данные, не код
query := "SELECT * FROM users WHERE id = $1"
row := db.QueryRow(query, id)
var u User
err := row.Scan(&u.ID, &u.Name, &u.Email)
return &u, err
}How to fix
Never concatenate SQL strings with user input. Use only parameterized queries (placeholders $1, ?), where the driver passes data separately from the query body — input cannot physically become part of the code. Validate table/column identifiers that can’t be parameterized against an allowlist. Grant DB privileges following the principle of least privilege.
Tools and practices
database/sql + placeholders— Standard library: db.Query("... WHERE id = $1", id). The basic approach, sufficient for most cases.sqlc— Generates type-safe Go code from plain SQL at build time. Queries are checked by the compiler, injections are excluded by design.ent (entgo.io)— An ORM from Meta with code generation and a type-safe query builder. Graph-oriented schema, no raw strings.GORM— A popular full-featured ORM. Parameterizes automatically; avoid Raw/Exec with concatenation.sqlx / squirrel— sqlx is a thin layer over database/sql; squirrel is a safe query builder that assembles parameterized queries.pgx— A high-performance PostgreSQL driver with native support for prepared statements and protocol-level binding.