SQL Injection Protection
SQL injection protection is absolute thanks to the exclusive use of prepared statements.
Protection mechanism
Section titled “Protection mechanism”// All queries use PrepareContext()stmt, err := s.db.PrepareContext(ctx, query)defer stmt.Close()rows, err := stmt.QueryContext(ctx, args...)Defense in depth
Section titled “Defense in depth”- Mandatory prepared statements — All queries use
PrepareContext() - Code and data separation — Parameters are passed as separate arguments
- No SQL string concatenation — The go-mssqldb driver handles escaping automatically
Blocked attack example
Section titled “Blocked attack example”-- Injection attempt:SELECT * FROM users WHERE username = '1' OR '1'='1' --
-- With prepared statements, it's treated as a literal:SELECT * FROM users WHERE username = '1'' OR ''1''=''1'' --'Additional protections
Section titled “Additional protections”Dangerous command blocking
Section titled “Dangerous command blocking”In read-only mode, these are blocked:
EXEC/EXECUTESP_/XP_(dangerous system procedures)OPENROWSET/OPENDATASOURCEBULK INSERTRECONFIGURE
Input validation
Section titled “Input validation”- Query size limit (1 MB by default, configurable)
- Empty input rejection
- Comment stripping that could hide commands
Security tests
Section titled “Security tests”# Run the SQL injection test suitego test -v -run TestSQLInjectionVulnerability ./test/security/...The tests cover 6 different attack vectors, all successfully blocked.