GuardAPI Logo
GuardAPI

Fix NoSQL Injection in Gin

NoSQL injection in the Go/Gin ecosystem typically manifests when developers pipe raw request parameters directly into MongoDB filter maps (bson.M). Attackers exploit this by injecting operator objects—like {"$ne": null}—to bypass authentication or dump databases. As a researcher, your goal is to enforce strict type boundaries between the transport layer and the data layer.

The Vulnerable Pattern

func Login(c *gin.Context) {
	// VULNERABLE: User provides a JSON body like {"username": {"$ne": ""}, "password": {"$ne": ""}}
	var input map[string]interface{}
	c.BindJSON(&input)
filter := bson.M{"user": input["username"], "pass": input["password"]}
var result User
err := collection.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
	c.JSON(401, gin.H{"error": "failed"})
	return
}
c.JSON(200, result)

}

The Secure Implementation

The exploit works because MongoDB drivers interpret nested maps as query operators. If you bind input to a generic map[string]interface{}, an attacker can pass a JSON object instead of a string. The fix is two-fold: First, use 'Strict Schema Binding' with Go structs and Gin's 'binding' tags to force the input into primitive types (strings). If the attacker sends an object, the binder will throw an error. Second, always construct your BSON filters using these validated variables rather than raw interface values from the request context.

type LoginReq struct {
	Username string `json:"username" binding:"required,alphanum"` 
	Password string `json:"password" binding:"required"` 
}

func Login(c *gin.Context) { var req LoginReq // SECURE: Strict struct binding enforces that input must be strings, not objects/operators if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, gin.H{“error”: “Invalid input”}) return }

// Use bson.D for ordered elements and explicit primitive values
filter := bson.D{{Key: "user", Value: req.Username}, {Key: "pass", Value: req.Password}}

var result User
err := collection.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
	c.JSON(401, gin.H{"error": "Unauthorized"})
	return
}
c.JSON(200, gin.H{"status": "success"})

}

System Alert • ID: 7382
Target: Gin API
Potential Vulnerability

Your Gin API might be exposed to NoSQL Injection

74% of Gin apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.