Skip to content

go.gin.missing_validation

Correctness Medium

Detects Gin handlers that bind request data without validation tags.

Unvalidated input causes problems:

  • Invalid data accepted — Garbage in, garbage out
  • Null pointer panics — Missing required fields cause crashes
  • Business logic errors — Constraints violated downstream
  • Security vulnerabilities — Unexpected input exploits assumptions

Gin has built-in validation through struct tags—use it.

// ❌ Before
type CreateUserRequest struct {
Email string `json:"email"`
Password string `json:"password"`
Age int `json:"age"`
}
func CreateUser(c *gin.Context) {
var req CreateUserRequest
c.ShouldBindJSON(&req) // No validation
// Empty email? Negative age? Anything goes.
}
// ✅ After
type CreateUserRequest struct {
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required,min=8"`
Age int `json:"age" binding:"gte=0,lte=150"`
}
func CreateUser(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// Email is valid, password has 8+ chars, age is reasonable
}
  • Struct bindings without binding: tags
  • Missing required on essential fields
  • ShouldBind without error checking

Unfault adds common validation tags based on field names and types.

type Request struct {
// Required fields
Name string `binding:"required"`
// String constraints
Email string `binding:"required,email"`
URL string `binding:"url"`
UUID string `binding:"uuid"`
// Numeric constraints
Age int `binding:"gte=0,lte=150"`
Count int `binding:"min=1,max=100"`
// Length constraints
Password string `binding:"min=8,max=128"`
Code string `binding:"len=6"`
// Enums
Status string `binding:"oneof=pending active done"`
}