Missing Input Validation Anti-Pattern
Severity: High
Summary
Missing input validation occurs when applications fail to validate data from users or external sources before processing it. This enables SQL Injection, Cross-Site Scripting (XSS), Command Injection, and Path Traversal attacks. Treat all incoming data as untrusted. Validate against strict rules for type, length, format, and range.
The Anti-Pattern
Trusting external input without server-side validation. Client-side validation provides no security—attackers bypass it trivially.
BAD Code Example
# VULNERABLE: Trusts user input completely, enabling SQL Injection
from flask import request
import sqlite3
@app.route("/api/products")
def search_products():
# Takes 'category' directly from URL query string
category = request.args.get("category")
# Input concatenated directly into SQL query (classic SQL Injection)
db = sqlite3.connect("database.db")
cursor = db.cursor()
query = f"SELECT id, name, price FROM products WHERE category = '{category}'"
# Attacker request: /api/products?category=' OR 1=1 --
# Resulting query: "SELECT ... FROM products WHERE category = '' OR 1=1 --'"
# Returns ALL products, bypassing filter
cursor.execute(query)
products = cursor.fetchall()
return {"products": products}
GOOD Code Example
# SECURE: Validates all input on server against strict allowlist
from flask import request
import sqlite3
# Strict allowlist of known-good values for 'category' parameter
ALLOWED_CATEGORIES = {"electronics", "books", "clothing", "homegoods"}
@app.route("/api/products/safe")
def search_products_safe():
category = request.args.get("category")
# 1. VALIDATE EXISTENCE: Check parameter provided
if not category:
return {"error": "Category parameter is required."}, 400
# 2. VALIDATE AGAINST ALLOWLIST: Strongest form of input validation
if category not in ALLOWED_CATEGORIES:
return {"error": "Invalid category specified."}, 400
# 3. USE PARAMETERIZED QUERIES: Safe database APIs prevent injection
db = sqlite3.connect("database.db")
cursor = db.cursor()
# '?' placeholder treats input as data, not code
query = "SELECT id, name, price FROM products WHERE category = ?"
cursor.execute(query, (category,))
products = cursor.fetchall()
return {"products": products}
Detection
- Trace user input: Follow HTTP request data (URL parameters, POST body, headers, cookies) through code. Verify validation occurs before use.
- Find client-side-only validation: Check for
required HTML attributes or JavaScript validation without server-side equivalents.
- Identify missing checks: Find input handling without type, length, format, or range validation.
Prevention
Apply "Validate, then Act" to all incoming data.
Related Security Patterns & Anti-Patterns
Missing input validation enables most major vulnerability classes.
References
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: missing-input-validation-anti-pattern3description: Security anti-pattern for missing input validation (CWE-20). Use when generating or reviewing code that processes user input, form data, API parameters, or external data. Detects client-only validation, missing type checks, and absent length limits. Foundation vulnerability enabling most attack classes. Use when this capability is needed.4---56# Missing Input Validation Anti-Pattern78**Severity:** High910## Summary1112Missing input validation occurs when applications fail to validate data from users or external sources before processing it. This enables SQL Injection, Cross-Site Scripting (XSS), Command Injection, and Path Traversal attacks. Treat all incoming data as untrusted. Validate against strict rules for type, length, format, and range.1314## The Anti-Pattern1516Trusting external input without server-side validation. Client-side validation provides no security—attackers bypass it trivially.1718### BAD Code Example1920```python21# VULNERABLE: Trusts user input completely, enabling SQL Injection22from flask import request23import sqlite32425@app.route("/api/products")26def search_products():27 # Takes 'category' directly from URL query string28 category = request.args.get("category")2930 # Input concatenated directly into SQL query (classic SQL Injection)31 db = sqlite3.connect("database.db")32 cursor = db.cursor()33 query = f"SELECT id, name, price FROM products WHERE category = '{category}'"3435 # Attacker request: /api/products?category=' OR 1=1 --36 # Resulting query: "SELECT ... FROM products WHERE category = '' OR 1=1 --'"37 # Returns ALL products, bypassing filter38 cursor.execute(query)39 products = cursor.fetchall()40 return {"products": products}41```4243### GOOD Code Example4445```python46# SECURE: Validates all input on server against strict allowlist47from flask import request48import sqlite34950# Strict allowlist of known-good values for 'category' parameter51ALLOWED_CATEGORIES = {"electronics", "books", "clothing", "homegoods"}5253@app.route("/api/products/safe")54def search_products_safe():55 category = request.args.get("category")5657 # 1. VALIDATE EXISTENCE: Check parameter provided58 if not category:59 return {"error": "Category parameter is required."}, 4006061 # 2. VALIDATE AGAINST ALLOWLIST: Strongest form of input validation62 if category not in ALLOWED_CATEGORIES:63 return {"error": "Invalid category specified."}, 4006465 # 3. USE PARAMETERIZED QUERIES: Safe database APIs prevent injection66 db = sqlite3.connect("database.db")67 cursor = db.cursor()68 # '?' placeholder treats input as data, not code69 query = "SELECT id, name, price FROM products WHERE category = ?"70 cursor.execute(query, (category,))71 products = cursor.fetchall()72 return {"products": products}73```7475## Detection7677- **Trace user input:** Follow HTTP request data (URL parameters, POST body, headers, cookies) through code. Verify validation occurs before use.78- **Find client-side-only validation:** Check for `required` HTML attributes or JavaScript validation without server-side equivalents.79- **Identify missing checks:** Find input handling without type, length, format, or range validation.8081## Prevention8283Apply "Validate, then Act" to all incoming data.8485- [ ] **Validate server-side:** Client-side validation provides UX, not security86- [ ] **Use allowlists:** Known-good lists beat known-bad blocklists87- [ ] **Apply multi-layer validation:**88 - **Type:** Verify expected type (number vs string)89 - **Length:** Enforce min/max to prevent buffer overflows and DoS90 - **Format:** Match expected patterns (email, phone regex)91 - **Range:** Verify numerical bounds92- [ ] **Use schema validation libraries:** For JSON/XML, use Pydantic, JSON Schema, or Marshmallow9394## Related Security Patterns & Anti-Patterns9596Missing input validation enables most major vulnerability classes.9798- [SQL Injection Anti-Pattern](../sql-injection/)99- [Cross-Site Scripting (XSS) Anti-Pattern](../xss/)100- [Command Injection Anti-Pattern](../command-injection/)101- [Path Traversal Anti-Pattern](../path-traversal/)102103## References104105- [OWASP Top 10 A05:2025 - Injection](https://owasp.org/Top10/2025/A05_2025-Injection/)106- [OWASP GenAI LLM05:2025 - Improper Output Handling](https://genai.owasp.org/llmrisk/llm05-improper-output-handling/)107- [OWASP API Security API8:2023 - Security Misconfiguration](https://owasp.org/API-Security/editions/2023/en/0xa8-security-misconfiguration/)108- [OWASP Input Validation Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)109- [CWE-20: Improper Input Validation](https://cwe.mitre.org/data/definitions/20.html)110- [CAPEC-153: Input Data Manipulation](https://capec.mitre.org/data/definitions/153.html)111- Source: [sec-context](https://github.com/Arcanum-Sec/sec-context)112113---114> Converted and distributed by [TomeVault](https://tomevault.io/claim/igbuend) — claim your Tome and manage your conversions.115<!-- tomevault:4.0:skill_md:2026-04-13 -->