On this page
  1. What is the difference between validation, escaping, and sanitization?
  2. When do you use each one?
  3. Why is context-specific escaping so important?
  4. Why are denylists and blacklists a bad idea?
  5. Where AI coding assistants get this wrong
  6. Checklist
  7. FAQ
    1. What is the difference between validation, escaping, and sanitization?
    2. Should I validate input or escape output?
    3. Is sanitizing dangerous?
    4. Does validating input prevent SQL injection?
    5. What is the difference between sanitizing and escaping?
    6. Is client-side validation enough?
  8. Related topics
  9. Sources
concept

Input Validation vs Escaping vs Sanitization: What's the Difference?

Validation, escaping, and sanitization are three different defenses used against injection. Learn which one to use, where, and why mixing them causes bugs.

Quick answer

  • Validation asks “is this value acceptable?” and rejects it if not. Escaping asks “how should this value be represented?” so it cannot be read as syntax. Sanitizing asks “strip the dangerous parts and keep the rest.”
  • They are not alternatives. A validated value still needs escaping, and escaping does not make a value valid.
  • Prefer validation and escaping. Sanitize only when you deliberately allow rich content.
  • Escaping is context-specific: HTML body, HTML attribute, JavaScript string, and URL each need different treatment.

What is the difference between validation, escaping, and sanitization?

These three words are used interchangeably, and they are not interchangeable. They defend against the same family of attacks — code injection — at three different points with three different guarantees.

Input validation decides whether a value is acceptable at all, by shape and range. A country field that must be one of a fixed list, a quantity that must be a positive integer, a date that must parse. Validation happens at the boundary, before the value is used in logic, and its answer is yes or no.

Output escaping takes a value you have already decided to accept and converts its characters into forms that the output context will render as literal text rather than executable syntax. < becomes &lt;, and the browser displays a bracket instead of starting a tag. Escaping happens at the moment of output, and it is context-specific.

Sanitization is the middle path: remove or neutralise known-dangerous constructs while leaving the value otherwise intact. It exists for the case where you genuinely want to allow some HTML — bold text, links, lists — and need to strip the rest. Sanitizing is the hardest of the three to get right, which is why it should be your last choice rather than your first.

Where this bites vibecoders

The specific way this bites vibecoders is the assistant reaching for sanitization because the word “sanitize” appears in the request (“sanitize the input”), then writing a function that strips <script> and calls it a day. That blacklist approach is bypassed in ways that are not obvious, because the payload does not have to use the literal string it removed. The generated function looks defensive, the code reads as handled, and the bug survives.

When do you use each one?

Validation — at the boundary, for business rules. Apply it to every request that crosses a trust boundary: the API, a form post, a webhook, a file upload, a query parameter. Use allowlists, not denylists: checking that country is in your list is reliable, while checking that country does not contain a bad word is not.

Escaping — at output, for the specific context. Apply it to every value that reaches HTML, an attribute, a JavaScript context, a URL, or a shell command, in the encoding appropriate to that context. This is the defense that actually stops cross-site scripting, and most frameworks do it for you automatically.

Sanitizing — only for deliberately rich content. Apply it when a product requirement means users can write HTML or Markdown that renders. Use a maintained, allowlist-based library, and understand that you are taking on responsibility for its correctness.

The ordering matters: validation is not a substitute for escaping, and escaping is preferable to sanitizing. A value that passes every validation rule you write can still contain characters that execute if you concatenate it into a query or a shell command.

Why is context-specific escaping so important?

Because “escaping” is not one operation. The same string needs different treatment depending on where it lands, and using the wrong encoding is a no-op at best.

ContextWhat must be encodedFailure if you use the wrong one
HTML body text<, >, &, ", 'Injected markup executes
HTML attribute valueAttribute-safe set, plus quote handlingBreak out of the attribute with a new handler
JavaScript string literalJS-specific escapes, and prefer JSON encodingBreak out of the string into executable code
URLPercent-encoding, plus scheme allowlistingjavascript: URL executes on click
Shell commandNever concatenate; pass arguments as an arrayCommand injection
SQLUse parameter binding, not string escapingSQL injection

The row that catches people is JavaScript. HTML-escaping a value and then embedding it in a <script> block does not help, because the browser never HTML-decodes inside a script. This is why frameworks that escape by default still have documented XSS paths — see What Is Cross-Site Scripting (XSS)?.

Why are denylists and blacklists a bad idea?

A denylist enumerates the bad thing and blocks it. The problem is that the space of bad inputs is much larger than any list you can write.

For markup, a filter removing <script> does nothing against an <img> with an event handler, a <svg> payload, or a differently-cased or entity-encoded tag. For paths, blocking .. misses URL-encoded variants, absolute paths, and symlinks. For filenames, blocking known extensions is a losing game against double extensions and unusual content types.

An allowlist inverts the logic: describe exactly what is permitted and reject everything else. A country field validated against ["US", "GB", "DE"] cannot be bypassed, because there is no way to express an invalid value that is still on the list. This is the single most important habit in input handling, and it is why “validate against a known set” is the advice that appears in What Is SQL Injection and What Is SSRF.

Where AI coding assistants get this wrong

  • Writing a blacklist sanitizer. Stripping <script> and calling the field sanitized — the most common and most dangerous generated pattern.
  • Validating input and treating that as sufficient, then interpolating the value into SQL, a shell command, or a URL.
  • HTML-escaping into a JavaScript context, which the browser never decodes, so the escaping is inert.
  • Sanitizing on input and escaping on output inconsistently, so a value is transformed twice or not at all depending on the path.
  • Validating types loosely — checking a field exists, but not that a numeric field is within range or that a date is real (February 30th is a string that passes a regex).
  • Trusting client-side validation. Checks in the browser are for user experience; the server must repeat every one of them.
  • No validation on webhook or file-upload paths, where the attacker controls the entire request shape.
  • Regex-based validation that is itself vulnerable to ReDoS, turning a safety check into an availability bug — see What Is ReDoS.

Checklist

  • Validate every value crossing a trust boundary, using allowlists rather than denylists.
  • Repeat all validation on the server, regardless of what the client checked.
  • Escape on output, in the encoding that matches the destination context.
  • Never rely on HTML escaping inside a JavaScript or URL context.
  • Use parameter binding for SQL, argument arrays for shell commands, and a query builder for URLs.
  • Sanitize only when rich content is a product requirement, using a maintained allowlist-based library.
  • Keep validation and rendering concerns separate so each value is handled once, deliberately.
  • Test that rejected input fails, not just that accepted input succeeds.
  • Add a static analysis rule for string concatenation into queries, shell commands, and markup.
  • Confirm the escape function you call is context-appropriate, not just named “escape”.

FAQ

What is the difference between validation, escaping, and sanitization?

Validation rejects input that does not fit an expected shape — a date that must be ISO, a country from a fixed list. Escaping converts characters so they are interpreted as data rather than syntax, and belongs at output. Sanitizing strips or transforms known-dangerous constructs while preserving the rest, and is what you use when you deliberately allow some HTML.

Should I validate input or escape output?

Both, and they are not alternatives. Validation is a business-logic check on whether the value is acceptable at all. Escaping is a rendering decision about how to represent a value you already accepted. Validation alone never makes a value safe to render, and escaping alone never makes a value acceptable to your business rules.

Is sanitizing dangerous?

Sanitizers are hard to get right and easy to misuse. Blacklist-based sanitizers, which strip known-bad strings, are routinely bypassed because there are more ways to express a payload than a list anticipates. Allowlist-based sanitizers, which keep only known-good constructs, are much safer. Where possible, escaping is preferable to sanitizing.

Does validating input prevent SQL injection?

Not by itself. Validation reduces the attack surface, but the defense against SQL injection is parameter binding, which keeps data and syntax separate regardless of content. An assistant that validates a username and then concatenates it into a query has added a check without adding the actual protection — see What Is SQL Injection?

What is the difference between sanitizing and escaping?

Escaping is lossless and reversible: the value is transformed into an unambiguous encoded form that renders as the original text. Sanitizing is lossy: dangerous parts are removed and the rest is kept, which means the value changes. Escape when you want to display something faithfully; sanitize only when you intend to interpret a subset of it.

Is client-side validation enough?

No. Anything enforced only in the browser can be skipped by calling the API directly, which is a two-line script. Treat client-side validation purely as a usability feature and enforce every rule again on the server, where it is the only check an attacker cannot bypass.

Sources

Share: