We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Safe Validation and Sanitization

User input is untrusted. I know we've been over this... sorry to beat a dead horse... but it's worth repeating.

Validation vs. Sanitization

Two key practices here are validation and sanitization, and they solve different problems.

  • Validation asks: is this input allowed? It usually happens at the application boundary, when input first arrives. Invalid requests get rejected immediately.
  • Sanitization deliberately transforms input according to a defined content policy. For example, a rich-text sanitizer might remove tags and attributes the application doesn't support.

Sanitization is different from context-specific escaping or encoding. HTML escaping, shell argument handling, and similar defenses belong deeper in the logic where the application knows how the value is being used. Validation usually happens earlier, and complements those defenses; it does not replace them.

Validate, Then Reject

For most user-provided data, the safest pattern is explicit validation followed by a hard reject on failure.

Imagine a user registration endpoint that accepts a username, limited to 20 alphanumeric characters. The endpoint could "sanitize" the input by dropping any invalid characters and applying a length cap:

var invalidUsernameCharacters = regexp.MustCompile(`[^a-zA-Z0-9]`)

cleanedName := invalidUsernameCharacters.ReplaceAllString(username, "")
if len(cleanedName) > 20 {
  cleanedName = cleanedName[:20]
}

But that doesn't make much sense... the user's input has been silently changed! You're going to create them a username they didn't type in?!? Bad. In this case, it would be simpler and safer to simply return an error on misshapen input:

var usernamePattern = regexp.MustCompile(`^[a-zA-Z0-9]{3,20}$`)

func isValidUsername(input string) bool {
  return usernamePattern.MatchString(input)
}

username := request.FormValue("username")
if !isValidUsername(username) {
  http.Error(responseWriter, "Invalid username", http.StatusBadRequest)
  return
}

Assignment

Bearly Secure parses cart quantities as floating-point numbers, so alternate numeric forms such as 1e1 can bypass the intended input format. Accept only canonical whole-number strings.

With Bearly Secure still running, run and submit the CLI tests from the project root.