SQL Injection via sqlx

CRITICAL

User-controlled input reaches sqlx query methods without parameterization — sqlx's convenience wrappers (Get, Select, NamedExec) are also vulnerable when used with raw string concatenation.

Rule Information

Language
Go
Category
Security
Author
Shivasurya
Shivasurya
Last Updated
2026-04-13
Tags
gosecuritysql-injectionsqlxCWE-89OWASP-A03
CWE References

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 .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
rule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Cross-file analysis: 3 files

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

1

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.

2

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.

3

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

OWASP Top 10
A03:2021 — Injection
CWE Top 25 (2024)
CWE-89 — SQL Injection (ranked #6)
PCI DSS v4.0
Requirement 6.2.4 — Protect against injection attacks

References

External resources and documentation

Similar Rules

Explore related security rules for Go

Frequently Asked Questions

Common questions about SQL Injection via sqlx

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.
Use Code Pathfinder to scan your codebase: pathfinder scan --ruleset golang/GO-SQLI-003 --project .
This vulnerability is rated as CRITICAL severity.
Yes! Code Pathfinder allows you to customize rules. Modify detection patterns, adjust severity levels, add custom sanitizers, and configure the rule to fit your organization's security policies.

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.

See how it works