Interactive Playground
Experiment with the vulnerable code and security rule below. Edit the code to see how the rule detects different vulnerability patterns.
pathfinder scan --ruleset golang/GO-SQLI-003 --project .About This Rule
Understanding the vulnerability and how it is detected
sqlx (github.com/jmoiron/sqlx) is a popular Go library that extends database/sql with struct scanning, named parameters, and more ergonomic query methods like Get, Select, and NamedExec. sqlx wraps database/sql and supports the same placeholder syntax ($1/$2 for PostgreSQL, ? for MySQL/SQLite).
Despite sqlx's convenience features, the underlying query execution is identical to database/sql — SQL injection occurs when user input is concatenated into the query string rather than passed as a parameterized argument.
**sqlx-specific pitfalls**: - `db.Get(&dest, "SELECT * FROM users WHERE id = " + id)` — vulnerable Get - `db.Select(&dest, query)` where query is built with fmt.Sprintf — vulnerable Select - `db.NamedExec(query, params)` where query string itself contains concatenation - `db.Queryx("SELECT " + column + " FROM table")` — dynamic column injection
**Named parameters** (`:name` syntax) in sqlx's NamedExec/NamedQuery are safe for values — but the query template string itself must not contain user input.
sqlx's `In()` helper is also worth noting: `sqlx.In("SELECT * WHERE id IN (?)", ids)` correctly handles expanding a slice to multiple placeholders. Do not build IN clauses manually with string concatenation.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Struct Scanning of Injected Data
sqlx's Get() and Select() scan query results directly into Go structs. SQL injection via these methods can return arbitrary data from any table, not just the target struct's table — the data is silently scanned into struct fields that match column names.
Authentication Bypass via Get()
`db.Get(&user, "SELECT * FROM users WHERE username='"+u+"' AND password='"+p+"'")` is bypassed by supplying `username=admin'--` which comments out the password check.
Dynamic Column/Table Injection
Injecting into SELECT column lists or table names is not preventable by parameterization alone. Dynamic schema or column selection must use strict allowlist validation.
How to Fix
Recommended remediation steps
- 1Use sqlx positional parameters ($1, ? depending on database driver) for all user values.
- 2Use sqlx.NamedExec / db.NamedQuery with :name syntax for complex struct-mapped queries.
- 3Use sqlx.In() for IN clauses with variable argument lists — never build them with join.
- 4For dynamic ORDER BY columns, validate against an explicit string allowlist.
- 5Validate numeric IDs with strconv.Atoi before use (also acts as a sanitizer).
- 6Keep sqlx and the underlying driver up to date.
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
Tracks taint from HTTP framework sources (net/http, gin, echo, fiber, chi) to sqlx DB/Tx/Stmt query methods (Query, QueryContext, Queryx, QueryRowx, Get, Select, NamedExec, NamedQuery, Exec, ExecContext) with global inter-procedural scope.
Compliance & Standards
Industry frameworks and regulations that require detection of this vulnerability
References
External resources and documentation
Similar Rules
Explore related security rules for Go
SQL Injection via database/sql
User-controlled input reaches database/sql query methods without parameterization, enabling SQL injection — ranked
SQL Injection via GORM Raw/Exec
User-controlled input flows into GORM Raw() or Exec() raw SQL methods without parameterization — GORM's ORM safety guarantees do not apply to Raw/Exec with string concatenation.
Frequently Asked Questions
Common questions about SQL Injection via sqlx
New feature
Get these findings posted directly on your GitHub pull requests
The SQL Injection via sqlx rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.