Go secure coding¶
Go's explicit error handling and static types do not stop untrusted strings from becoming SQL or shell instructions. This guide uses database/sql with a PostgreSQL driver in an HTTP service. PostgreSQL placeholders use $1; use the syntax required by your own driver.
Pass query arguments separately¶
Assume db is an open *sql.DB, ctx is the request context, and name is a validated string. These snippets belong inside a function that returns an error.
Unsafe: format the value into SQL.
query := fmt.Sprintf("SELECT id FROM customers WHERE name = '%s'", name)
rows, err := db.QueryContext(ctx, query)
if err != nil {
return err
}
defer rows.Close()
Safer: leave the query fixed.
rows, err := db.QueryContext(
ctx, "SELECT id FROM customers WHERE name = $1", name,
)
if err != nil {
return err
}
defer rows.Close()
The driver receives the parameter separately. The Go project's SQL injection guide recommends passing arguments instead of formatting values into a query. After iterating, check rows.Err() so a read failure is not treated as a successful empty result. Retain the request's timeout or cancellation context.
Binding does not authorize the lookup. Add an authenticated tenant or owner condition to the query and parameterize that value too. Dynamic sort keys need a fixed mapping to permitted SQL fragments. Keep database credentials limited to the operations the service needs.
Check the fix¶
Seed a disposable database with O'Reilly and Example Workshop. Confirm each lookup returns only its own record. Test an already-cancelled context and verify that the handler returns a controlled failure. Also test a valid identifier owned by a different user; it must not become accessible because the query is syntactically safe.
Review SQL injection, command injection, path traversal and TLS validation. For HTML templates, avoid converting untrusted strings into trusted HTML types. OWASP's SQL guidance explains least privilege and identifier allowlists.
Examples establish a specific programming pattern. A scanner's language support does not imply complete analysis of every framework, generated file or runtime path.