---
title: Always Validate Client Data Server-side
impact: MEDIUM
impactDescription: ensures input validation cannot be bypassed
tags: validation, server-side, input, sanitization, security
---

## Always Validate Client Data Server-side

Client-side validation is for UX only - it can be bypassed easily. All input must be validated server-side.

**Incorrect (trusting client validation):**

```go
// No server validation - trusting frontend
func TransferHandler(w http.ResponseWriter, r *http.Request) {
    amount, _ := strconv.Atoi(r.FormValue("amount"))
    toAccount := r.FormValue("toAccount")
    transferMoney(r.Context().Value("userId").(string), toAccount, amount)
}
```

**Correct (comprehensive server validation):**

```go
import "github.com/go-playground/validator/v10"

type TransferRequest struct {
    Amount    int    `validate:"required,gt=0,lte=10000"`
    ToAccount string `validate:"required,printascii,len=20"`
}

func TransferHandler(w http.ResponseWriter, r *http.Request) {
    var req TransferRequest
    // Parse and validate
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        http.Error(w, "Invalid request", 400)
        return
    }
    
    validate := validator.New()
    if err := validate.Struct(req); err != nil {
        http.Error(w, err.Error(), 400)
        return
    }
    
    // Additional business validation
    if !accountExists(req.ToAccount) {
        http.Error(w, "Account not found", 404)
        return
    }
    
    transferMoney(r.Context().Value("userId").(string), req.ToAccount, req.Amount)
}
```

**Tools:** `go-playground/validator`, `ozzo-validation`, `asaskevich/govalidator`
