Overview
Injection vulnerabilities in real-world Go (Gin) apps can lead to severe data exposure, unauthorized data modification, or remote code execution in some scenarios. SQL injection, in particular, arises when user input is concatenated into queries, allowing attackers to alter query logic or access restricted data. OS command injection or template injection may also occur if user input reaches shell invocations or template engines without proper sanitization. The impact can span from data leakage to account compromise, depending on context and the backend services involved. While no CVEs are provided here, these risks are well-known in web frameworks and languages that interact with databases and system processes, making secure coding practices essential for Go (Gin) applications.
Code Fix Example
Go (Gin) API Security Remediation
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
func main() {
var err error
db, err = sql.Open("mysql", "user:password@tcp(localhost:3306)/mydb")
if err != nil {
log.Fatal(err)
}
defer db.Close()
r := gin.Default()
r.GET("/user/vuln", userVulnHandler)
r.GET("/user/safe", userSafeHandler)
r.Run(":8080")
}
// Vulnerable example (for reference): escapes are not applied and user input is interpolated into SQL
func userVulnHandler(c *gin.Context) {
email := c.Query("email")
query := fmt.Sprintf("SELECT id, name FROM users WHERE email = '%s'", email)
rows, err := db.Query(query)
if err != nil {
c.String(http.StatusInternalServerError, "error")
return
}
defer rows.Close()
count := 0
for rows.Next() {
count++
}
c.String(http.StatusOK, fmt.Sprintf("vulnerable: %d rows", count))
}
// Fixed: parameterized query using a placeholder to prevent injection
func userSafeHandler(c *gin.Context) {
email := c.Query("email")
rows, err := db.Query("SELECT id, name FROM users WHERE email = ?", email)
if err != nil {
c.String(http.StatusInternalServerError, "error")
return
}
defer rows.Close()
count := 0
for rows.Next() {
count++
}
c.String(http.StatusOK, fmt.Sprintf("safe: %d rows", count))
}