mcpField
I
input-validation

input-validation

github.com/yanko-belov安全1337 次安装40 周前更新
代码仓库

关于 input-validation

input-validation 是面向开发者的安全技能,强调在系统边界验证不可信数据。它列出验证标准、基于模式的做法、风险信号,以及应对跳过验证的常见借口的方法。

主要功能

  1. 01在入口处验证外部数据
  2. 02检查类型、格式、范围和必填项
  3. 03采用基于模式的验证方式
  4. 04识别不安全的输入处理模式
  5. 05反驳跳过验证的常见理由

适用场景

  1. 01写入数据库前验证 HTTP 请求数据
  2. 02检查文件、环境变量和 API 输入
  3. 03审查代码中的未验证输入

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yanko-belov/code-craft --skill input-validation

安装后在 Claude Code 中输入/input-validation确认已加载。

详细介绍

输入验证

概述

永远不要信任输入。在系统边界验证所有内容。

所有外部数据都可能是恶意或格式错误的。在数据入口处进行验证,并在输入无效时快速失败。

适用场景

  • 处理 HTTP 请求正文、参数和标头
  • 读取文件或环境变量
  • 接收来自外部 API 的数据
  • 任何接收不可信输入的函数

铁律

NEVER use external input without explicit validation.

没有例外:

  • 不能因为“前端会验证”
  • 不能因为“这是内部 API”
  • 不能因为“我们信任来源”
  • 不能因为“这只是一个简单字段”

检测:信任隐患

如果你在直接使用输入,请立即停止:

// ❌ 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 });
});

问题:

  • email 可能为空、为 null,或不是字符串
  • age 可能为负数、字符串,或缺失
  • 根据使用方式,可能出现 SQL 注入、XSS

正确做法:在边界处验证

// ✅ 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 });
});

验证规则

始终验证:
  • 类型:它是字符串、数字还是布尔值?
  • 格式:电子邮件是否有效?UUID 是否有效?
  • 范围:最小/最大长度是多少?数值边界是多少?
  • 必填:它是否存在?
  • 清理:必要时移除危险字符
验证库示例:
// 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;
}

抵御施压的应对方案

1. “前端会验证”

施压说法:“表单已经验证过这些数据了”

**回应:**前端验证是为了改善用户体验。后端验证是为了安全。攻击者可以绕过前端。

**行动:**无论前端是否验证,都要在后端进行验证。

2. “这是内部 API”

施压说法:“只有我们的服务会调用这个端点”

**回应:**内部服务也会有漏洞。纵深防御要求在所有地方进行验证。

**行动:**也要验证内部 API 的输入。

3. “我们信任来源”

施压说法:“这些数据来自合作伙伴的 API”

**回应:**对方的 API 可能有漏洞、遭到入侵或更改格式。不要信任任何人。

**行动:**使用外部 API 响应之前先进行验证。

4. “只是一个简单字段”

施压说法:“这只是一个字符串,能出什么问题?”

**回应:**字符串可能为空、过长,也可能包含脚本、SQL 或空字节。

**行动:**明确“有效”的定义并强制执行。

危险信号——立即停止并重新考虑

  • 未经验证就执行 const { x } = req.body
  • 对输入使用 any 类型
  • 输入无效时没有错误响应
  • “客户端会正确发送这些数据”
  • 解析输入时没有使用 try/catch

以上情况都意味着:添加验证。

快速参考

输入类型验证内容
电子邮件格式、长度、必填
密码长度、复杂度
ID格式(uuid/int)、是否存在
数字类型、范围、是否为整数?
字符串长度、模式、清理
数组长度、数组项验证
对象模式验证

常见借口(均不成立)

借口实际情况
“前端会验证”攻击者可以绕过前端。
“内部 API”内部也会有漏洞。
“我们信任来源”来源可能遭到入侵。
“简单字段”简单字段也会导致复杂漏洞。
“验证很慢”验证比安全漏洞造成的损失更快。
“TypeScript 类型就够了”类型在运行时会消失。

核心要点

验证所有输入。不要信任任何内容。数据无效时快速失败。

每个外部边界都应该进行明确验证。使用模式验证库。对无效输入返回清晰的错误消息。绝不要让未经验证的数据进入系统。

评论

支持 Markdown