Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Secure Coding  ›  Lesson

Input Validation Patterns

Input Validation Patterns 12 minValidate every input on the server, at the boundary, against an allow-list of what is expected, checking both format and business rules, and reject what fails.

Input Validation Patterns

Tiffin's order form limits quantity to 1–20 with a nice dropdown. Then someone sends quantity=-5 straight to the API with a command-line tool, and gets a refund-shaped order. The dropdown never ran. Every input that crosses into your system needs checking where the attacker cannot skip it.

The rule

Validate on the server, at the boundary, against what you expect.

  • On the server. Browser checks are for user comfort. Anyone can send a request without a browser.
  • At the boundary. Check input the moment it enters: API request, file upload, message from a queue, webhook. Then the rest of the code can trust its types.
  • Against what you expect. An allow-list describes what is valid ("an integer from 1 to 20"). A deny-list tries to name what is bad ("no <script>") and always misses something.

Check two layers:

  • Syntactic: type, length, format. Is delivery_date a real date?
  • Semantic: business rules. Is it not in the past? Does dish_id exist on today's menu?

When input fails, reject it with a clear error. Do not quietly "fix" it: silently trimming or rewriting input hides attacks and bugs.

A schema library makes this declarative:

from datetime import date
from pydantic import BaseModel, Field, field_validator

class OrderIn(BaseModel):
    dish_id: int = Field(gt=0)
    quantity: int = Field(ge=1, le=20)
    delivery_date: date
    note: str = Field(default="", max_length=200)

    @field_validator("delivery_date")
    @classmethod
    def not_in_past(cls, d: date) -> date:
        if d < date.today():
            raise ValueError("delivery date is in the past")
        return d

Validation is not a substitute for parameterized queries or output encoding. A note that passes every rule may still contain quotes and angle brackets. Validation narrows what gets in; the other defences handle it safely where it is used.

The shortcut

For each field, fill in one sentence: "It must be a ___, between ___ and ___, and it must make sense because ___." If you cannot finish the sentence, you do not know what valid means yet.

Validating one Tiffin orderStep 1 of 4
  1. quantity = -5

    "An integer between 1 and 20." Fails. Reject with 422.

Drills

Answer fast — trust the rule.

quick drill

Tiffin validates quantity only in the browser's JavaScript. What is the problem?

quick drill

Which rule is an allow-list?

quick drill

"The delivery date must not be in the past" is what kind of check?

quick drill

A note passes validation and contains O'Brien <3. What should happen next?

Remember

  • Validate on the server, at the boundary, against what you expect.
  • Finish the sentence: a ___, between ___ and ___, that makes sense because ___.
  • Reject, don't silently fix; validation never replaces parameters or encoding.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainDesign an order validator

Design the validation for Tiffin's POST /orders endpoint, which receives dish_id, quantity, delivery_date and a free-text note. Explain where validation runs, what you check for each field, and why validation does not replace parameterized queries or output encoding.