GORM: SQL Injection via raw queries
Go applications commonly use GORM or sqlx to interact with databases. While GORM parameterizes queries by default, developers looking to execute custom queries often fall back to raw string concatenation, creating SQL injection (SQLi) vulnerabilities:
// VULNERABLE GORM raw query pattern
func GetUser(db *gorm.DB, username string) (*User, error) {
var user User
// Concatenation bypasses prepared statement parameters!
err := db.Raw("SELECT * FROM users WHERE username = '" + username + "'").Scan(&user).Error
return &user, err
} The Fix: Force the use of placeholder markers (?) to bind parameters securely. GORM sanitizes all values bound via parameters:
// SECURE GORM query pattern
func GetUser(db *gorm.DB, username string) (*User, error) {
var user User
// Secure parameter binding
err := db.Raw("SELECT * FROM users WHERE username = ?", username).Scan(&user).Error
return &user, err
} Fiber: request context leaks in Goroutines
The Fiber framework is built on the fast fasthttp library. To achieve high speed, fasthttp recycles request context structures (*fibers.Ctx) after the request handler returns. If a developer spawns a goroutine inside the handler and passes the raw request context directly, a data race occurs. The goroutine reads memory that has already been overwritten by a subsequent HTTP request:
// VULNERABLE Fiber context usage in goroutines
app.Post("/api/log", func(c *fiber.Ctx) error {
go func() {
// Flaw: c is recycled! Under load, this prints data from other active users' requests
fmt.Println("Processing log for path:", c.Path())
}()
return c.SendStatus(200)
}) The Fix: Copy all required strings or values out of the context object before spawning the concurrent goroutine, or use c.Copy() to clone the context safely.
Gin: JSON Bind parameter pollution
In the Gin framework, developers use c.ShouldBindJSON() to bind incoming payloads to structs. If the target struct contains fields that are not marked with binding tags, or if you bind directly to database models, attackers can inject unlisted fields to manipulate internal application settings. We check that your endpoints utilize explicit binding schemas with strict tag constraints.
Fasthttp context recycling leaks payment headers
During an audit of a high-throughput payment proxy built on Go Fiber, we identified a handler that logged metadata asynchronously inside a goroutine without copying context values. By sending concurrent requests, we successfully caused a context data race, printing authorization headers and JWTs belonging to adjacent users in our logs. Fix priority: critical. Remediated by utilizing string copies before invoking goroutines.
Building high-concurrency microservices in Go? Schedule a secure code audit.
Book a Go API PentestFrequently asked questions
Why is unsafe memory allocation a risk in Go APIs?
While Go is memory-safe, using the `unsafe` package or failing to validate slice lengths when reading payloads can cause excessive RAM allocation, allowing attackers to trigger Out Of Memory (OOM) crashes (Denial of Service).
How do you prevent SQL injection in Go ORMs like GORM?
Avoid raw SQL string formatting inside GORM methods. GORM utilizes parameterized statements by default (e.g., `db.Where("name = ?", userInput)`), but concatenating variables (e.g., `db.Where("name = " + userInput)`) bypasses this protection.
What is the security difference between Gin and Fiber?
Gin is built on net/http, while Fiber utilizes valyala/fasthttp. Fasthttp optimizes memory allocation by reusing request contexts, which can lead to data races and context leaks if goroutines are managed incorrectly.
Related reading
Blog: Flask API security · Django API security · API data leaks
Services: API security testing · Secure architecture review