input-validation
Use when accepting user input. Use when handling request data. Use when trusting external data without validation.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when accepting user input. Use when handling request data. Use when trusting external data without validation.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | input-validation |
| description | Use when accepting user input. Use when handling request data. Use when trusting external data without validation. |
Never trust input. Validate everything at system boundaries.
All external data is potentially malicious or malformed. Validate at the point of entry, fail fast on invalid input.
NEVER use external input without explicit validation.
No exceptions:
If you're using input directly, STOP:
// ❌ VIOLATION: Trusting input
app.post('/users', async (req, res) => {
const { email, age } = req.body; // Direct destructure - no validation
await db.users.create({ email, age });
res.json({ success: true });
});
Problems:
email could be empty, null, or not a stringage could be negative, a string, or missing// ✅ CORRECT: Validate with schema
import { z } from 'zod';
const createUserSchema = z.object({
email: z.string().email('Invalid email format'),
age: z.number().int().min(13).max(120),
name: z.string().min(1).max(100),
});
app.post('/users', async (req, res) => {
// Validate
const result = createUserSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
error: 'Validation failed',
details: result.error.flatten().fieldErrors
});
}
// Now data is typed and validated
const { email, age, name } = result.data;
await db.users.create({ email, age, name });
res.status(201).json({ success: true });
});
// Zod (recommended for TypeScript)
const schema = z.object({
id: z.string().uuid(),
email: z.string().email(),
age: z.number().min(0).max(150),
role: z.enum(['user', 'admin']),
tags: z.array(z.string()).max(10),
});
// Yup
const schema = yup.object({
email: yup.string().email().required(),
age: yup.number().positive().integer(),
});
// class-validator
class CreateUserDto {
@IsEmail()
email: string;
@IsInt()
@Min(13)
age: number;
}
Pressure: "The form already validates this data"
Response: Frontend validation is for UX. Backend validation is for security. Attackers bypass frontends.
Action: Validate on backend regardless of frontend validation.
Pressure: "Only our services call this endpoint"
Response: Internal services have bugs too. Defense in depth requires validation everywhere.
Action: Validate internal API inputs too.
Pressure: "This data comes from our partner's API"
Response: Their API can have bugs, be compromised, or change format. Trust no one.
Action: Validate external API responses before using.
Pressure: "It's just a string, what could go wrong?"
Response: Strings can be empty, too long, contain scripts, SQL, or null bytes.
Action: Define what "valid" means and enforce it.
const { x } = req.body without validationany type for inputAll of these mean: Add validation.
| Input Type | Validate |
|---|---|
| Format, length, required | |
| Password | Length, complexity |
| ID | Format (uuid/int), exists |
| Number | Type, range, integer? |
| String | Length, pattern, sanitize |
| Array | Length, item validation |
| Object | Schema validation |
| Excuse | Reality |
|---|---|
| "Frontend validates" | Attackers bypass frontends. |
| "Internal API" | Internal bugs exist too. |
| "We trust the source" | Sources can be compromised. |
| "Simple field" | Simple fields cause complex bugs. |
| "Validation is slow" | Validation is faster than breaches. |
| "TypeScript types are enough" | Types disappear at runtime. |
Validate all input. Trust nothing. Fail fast on invalid data.
Every external boundary should have explicit validation. Use schema validation libraries. Return clear error messages for invalid input. Never let unvalidated data into your system.
Use when writing tests. Use when test structure is unclear. Use when arrange/act/assert phases are mixed.
Use when designing or modifying APIs. Use when adding breaking changes. Use when clients depend on API stability.
Use when implementing authentication. Use when storing passwords. Use when asked to store credentials insecurely.
Use when same data is fetched repeatedly. Use when database queries are slow. Use when implementing caching without invalidation strategy.
Use when tempted to use class inheritance. Use when creating class hierarchies. Use when subclass needs only some parent behavior.
Use when acquiring multiple locks. Use when operations wait for each other. Use when system hangs without crashing.