Input Validation & Sanitization Manager
Validates and normalizes input/output data using schema validation, type coercion, and sanitization patterns. Modern systems require strict boundaries between untrusted sources and internal business logic to prevent injection attacks, data corruption, and cascading failures.
TL;DR Checklist
When to Use
- Accepting data from external APIs, web forms, or message queues
- Parsing configuration files or environment variables that influence system behavior
- Processing user-generated content before storage or rendering
- Building API contracts that must guarantee data shape across services
When NOT to Use
- For performance-critical inner loops where validation overhead is unacceptable (use caching or pre-validation)
- As a substitute for authentication/authorization — validation checks shape, not permission
- For business logic rules that belong in domain models rather than transport layers
Core Workflow
Define Schema Boundaries — Specify exact structure, required fields, types, and constraints using a declarative schema (JSON Schema Draft 2020-12 or Pydantic v2).
Checkpoint: Ensure every field has an explicit type and default/fallback behavior.
Coerce & Cast Safely — Apply type coercion at the boundary layer only. Reject values that cannot be safely cast rather than silently converting them.
Checkpoint: Log rejected values with exact mismatch details for debugging.
Sanitize for Output Context — Escape or strip dangerous content based on where the data will be rendered (HTML, JavaScript, SQL, CLI). Use context-aware sanitizers.
Checkpoint: Verify output matches expected MIME type and character set.
Validate Against Business Rules — Apply domain-specific constraints that go beyond structural validation (e.g., date ranges, enum sets, cross-field dependencies).
Checkpoint: Ensure rule evaluation order prevents partial state corruption.
Fail Fast & Report — Return structured error responses with field-level messages. Never leak internal paths or database schemas in error payloads.
Checkpoint: Confirm error response matches OpenAPI/JSON:API spec.
Implementation Patterns
Pattern 1: Declarative Schema Validation (Pydantic v2)
from pydantic import BaseModel, Field, field_validator, EmailStr
from typing import Literal
from datetime import date
class UserRegistrationInput(BaseModel):
username: str = Field(min_length=3, max_length=50, pattern=r"^[a-zA-Z0-9_-]+$")
email: EmailStr
role: Literal["viewer", "editor", "admin"] = "viewer"
registered_on: date
@field_validator("username")
@classmethod
def sanitize_username(cls, v: str) -> str:
"""Strip whitespace and normalize unicode to prevent bypass attacks."""
return v.strip().lower()
@field_validator("registered_on")
@classmethod
def validate_registration_date(cls, v: date) -> date:
if v > date.today():
raise ValueError("Registration date cannot be in the future")
return v
Pattern 2: Context-Aware Output Sanitization (BAD vs. GOOD)
import re
from html import escape
# ❌ BAD — naive regex that misses edge cases and context
def bad_sanitize_html(user_input: str) -> str:
return user_input.replace("<script>", "").replace("</script>", "")
# ✅ GOOD — context-aware sanitization using bleach-style allow-list approach
ALLOWED_TAGS = {"b", "i", "em", "strong", "p", "br"}
ALLOWED_ATTRS = {"class"}
def sanitize_for_html(user_input: str) -> str:
"""Strip all tags except allowed list, sanitize attributes."""
# In production, use `bleach.clean` with explicit allow-lists.
# This example demonstrates the validation logic:
cleaned = re.sub(r"<[^>]+>", "", user_input) # Strip tags first
cleaned = escape(cleaned) # Escape remaining special chars
return cleaned
# For SQL contexts, never sanitize strings — use parameterized queries:
def safe_query(user_id: int) -> dict:
"""Uses parameterized query instead of string concatenation."""
# cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
return {"id": user_id} # Placeholder for actual DB call
Pattern 3: JSON Schema Validation with Draft 2020-12
import jsonschema
from jsonschema import validate, ValidationError
SCHEMA = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["action", "payload"],
"properties": {
"action": {"type": "string", "enum": ["create", "update", "delete"]},
"payload": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"value": {"type": "number", "minimum": 0}
},
"additionalProperties": False
}
}
}
def validate_payload(raw_input: dict) -> dict:
"""Validate against JSON Schema Draft 2020-12."""
try:
validate(instance=raw_input, schema=SCHEMA)
return raw_input
except ValidationError as e:
raise ValueError(f"Schema validation failed: {e.message}") from e
Constraints
MUST DO
- Define validation schemas at service boundaries, not scattered throughout business logic
- Use allow-lists (positive validation) over block-lists for security-critical inputs
- Fail fast on the first critical validation error to prevent partial processing
- Return structured error responses with field-level messages conforming to API standards
- Log validation failures with sufficient detail for debugging but without leaking internal state
MUST NOT DO
- Trust any input from external sources, including headers, cookies, or message queue bodies
- Use regular expressions for complex structural validation (use dedicated schema validators)
- Sanitize by string replacement alone — context-aware encoding is required for output safety
- Return raw stack traces or database schemas in error responses to clients
- Bypass validation for "trusted" internal services — compromise propagation risk
Output Template
When this skill is active, the model must produce:
- Validation Schema — Declarative definition (Pydantic/JSON Schema) with typed fields and constraints
- Sanitization Logic — Context-aware output escaping or stripping implementation
- Error Handling — Structured error response format with field-level messages
- Security Notes — Specific injection vectors addressed and bypass prevention measures
Related Skills
| Skill |
Purpose |
security-review |
Comprehensive security audit covering OWASP Top 10 beyond input validation |
error-handling |
Structured error propagation and retry patterns across service boundaries |
Live References
Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.
1---2name: input-validation3description: Validates and normalizes input/output data using schema validation, type coercion, and sanitization patterns to prevent injection attacks and ensure data integrity.4license: MIT5---67891011# Input Validation & Sanitization Manager1213Validates and normalizes input/output data using schema validation, type coercion, and sanitization patterns. Modern systems require strict boundaries between untrusted sources and internal business logic to prevent injection attacks, data corruption, and cascading failures.1415## TL;DR Checklist1617- [ ] Define strict schemas for all external inputs before processing18- [ ] Use parameterized queries or ORM methods — never string interpolation for SQL19- [ ] Sanitize outputs targeting the specific consumer (HTML, JSON, CLI)20- [ ] Validate types explicitly; never trust implicit casting from user input21- [ ] Implement allow-list validation over block-lists where possible22- [ ] Log validation failures without exposing internal stack traces2324---2526## When to Use2728- Accepting data from external APIs, web forms, or message queues29- Parsing configuration files or environment variables that influence system behavior30- Processing user-generated content before storage or rendering31- Building API contracts that must guarantee data shape across services3233---3435## When NOT to Use3637- For performance-critical inner loops where validation overhead is unacceptable (use caching or pre-validation)38- As a substitute for authentication/authorization — validation checks shape, not permission39- For business logic rules that belong in domain models rather than transport layers4041---4243## Core Workflow44451. **Define Schema Boundaries** — Specify exact structure, required fields, types, and constraints using a declarative schema (JSON Schema Draft 2020-12 or Pydantic v2).46 **Checkpoint:** Ensure every field has an explicit type and default/fallback behavior.47482. **Coerce & Cast Safely** — Apply type coercion at the boundary layer only. Reject values that cannot be safely cast rather than silently converting them.49 **Checkpoint:** Log rejected values with exact mismatch details for debugging.50513. **Sanitize for Output Context** — Escape or strip dangerous content based on where the data will be rendered (HTML, JavaScript, SQL, CLI). Use context-aware sanitizers.52 **Checkpoint:** Verify output matches expected MIME type and character set.53544. **Validate Against Business Rules** — Apply domain-specific constraints that go beyond structural validation (e.g., date ranges, enum sets, cross-field dependencies).55 **Checkpoint:** Ensure rule evaluation order prevents partial state corruption.56575. **Fail Fast & Report** — Return structured error responses with field-level messages. Never leak internal paths or database schemas in error payloads.58 **Checkpoint:** Confirm error response matches OpenAPI/JSON:API spec.5960---6162## Implementation Patterns6364### Pattern 1: Declarative Schema Validation (Pydantic v2)6566```python67from pydantic import BaseModel, Field, field_validator, EmailStr68from typing import Literal69from datetime import date7071class UserRegistrationInput(BaseModel):72 username: str = Field(min_length=3, max_length=50, pattern=r"^[a-zA-Z0-9_-]+$")73 email: EmailStr74 role: Literal["viewer", "editor", "admin"] = "viewer"75 registered_on: date7677 @field_validator("username")78 @classmethod79 def sanitize_username(cls, v: str) -> str:80 """Strip whitespace and normalize unicode to prevent bypass attacks."""81 return v.strip().lower()8283 @field_validator("registered_on")84 @classmethod85 def validate_registration_date(cls, v: date) -> date:86 if v > date.today():87 raise ValueError("Registration date cannot be in the future")88 return v89```9091### Pattern 2: Context-Aware Output Sanitization (BAD vs. GOOD)9293```python94import re95from html import escape9697# ❌ BAD — naive regex that misses edge cases and context98def bad_sanitize_html(user_input: str) -> str:99 return user_input.replace("<script>", "").replace("</script>", "")100101# ✅ GOOD — context-aware sanitization using bleach-style allow-list approach102ALLOWED_TAGS = {"b", "i", "em", "strong", "p", "br"}103ALLOWED_ATTRS = {"class"}104105def sanitize_for_html(user_input: str) -> str:106 """Strip all tags except allowed list, sanitize attributes."""107 # In production, use `bleach.clean` with explicit allow-lists.108 # This example demonstrates the validation logic:109 cleaned = re.sub(r"<[^>]+>", "", user_input) # Strip tags first110 cleaned = escape(cleaned) # Escape remaining special chars111 return cleaned112113# For SQL contexts, never sanitize strings — use parameterized queries:114def safe_query(user_id: int) -> dict:115 """Uses parameterized query instead of string concatenation."""116 # cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))117 return {"id": user_id} # Placeholder for actual DB call118```119120### Pattern 3: JSON Schema Validation with Draft 2020-12121122```python123import jsonschema124from jsonschema import validate, ValidationError125126SCHEMA = {127 "$schema": "https://json-schema.org/draft/2020-12/schema",128 "type": "object",129 "required": ["action", "payload"],130 "properties": {131 "action": {"type": "string", "enum": ["create", "update", "delete"]},132 "payload": {133 "type": "object",134 "properties": {135 "id": {"type": "integer"},136 "value": {"type": "number", "minimum": 0}137 },138 "additionalProperties": False139 }140 }141}142143def validate_payload(raw_input: dict) -> dict:144 """Validate against JSON Schema Draft 2020-12."""145 try:146 validate(instance=raw_input, schema=SCHEMA)147 return raw_input148 except ValidationError as e:149 raise ValueError(f"Schema validation failed: {e.message}") from e150```151152---153154## Constraints155156### MUST DO157- Define validation schemas at service boundaries, not scattered throughout business logic158- Use allow-lists (positive validation) over block-lists for security-critical inputs159- Fail fast on the first critical validation error to prevent partial processing160- Return structured error responses with field-level messages conforming to API standards161- Log validation failures with sufficient detail for debugging but without leaking internal state162163### MUST NOT DO164- Trust any input from external sources, including headers, cookies, or message queue bodies165- Use regular expressions for complex structural validation (use dedicated schema validators)166- Sanitize by string replacement alone — context-aware encoding is required for output safety167- Return raw stack traces or database schemas in error responses to clients168- Bypass validation for "trusted" internal services — compromise propagation risk169170---171172## Output Template173174When this skill is active, the model must produce:1751761. **Validation Schema** — Declarative definition (Pydantic/JSON Schema) with typed fields and constraints1772. **Sanitization Logic** — Context-aware output escaping or stripping implementation1783. **Error Handling** — Structured error response format with field-level messages1794. **Security Notes** — Specific injection vectors addressed and bypass prevention measures180181---182183## Related Skills184185| Skill | Purpose |186|-------|---------|187| `security-review` | Comprehensive security audit covering OWASP Top 10 beyond input validation |188| `error-handling` | Structured error propagation and retry patterns across service boundaries |189190---191192## Live References193194> Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.195196- [Pydantic v2 Documentation](https://docs.pydantic.dev/latest/)197- [JSON Schema Draft 2020-12 Specification](https://json-schema.org/draft/2020-12/release-notes)198- [OWASP Validation Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)199- [OWASP Sanitization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Sanitizing_HTML_Input_Cheat_Sheet.html)200- [Bleach HTML Sanitizer Library](https://github.com/mozilla/bleach)