关于 defense-in-depth-validation
Defense-in-Depth Validation 是一种分层验证实践指南,面向需要降低无效数据引发错误风险的开发者。它将检查分布在入口、业务逻辑、环境防护和调试记录等层面。
主要功能
- 01入口参数校验
- 02业务逻辑校验
- 03环境安全防护
- 04调试信息记录
适用场景
- 01避免无效路径触发错误的 Git 操作
- 02检查多条数据流中的验证缺口
- 03为多租户请求添加分层授权检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill defense-in-depth-validation安装后在 Claude Code 中输入/defense-in-depth-validation确认已加载。
详细介绍
纵深验证
概述
修复由无效数据引起的错误时,在一处添加验证似乎就足够了。但这项单独的检查可能被不同的代码路径、重构或模拟绕过。
**核心原则:**在数据经过的每一层都进行验证,让错误在结构上无法发生。
为什么需要多层
单层验证:“我们修复了错误” 多层验证:“我们让错误不可能发生”
不同层可以捕获不同情况:
- 入口验证可捕获大多数错误
- 业务逻辑可捕获边缘情况
- 环境保护措施可防止特定上下文中的危险操作
- 调试日志有助于在其他层失效时排查问题
四个层级
第 1 层:入口验证
**目的:**在 API 边界拒绝明显无效的输入
function createProject(name: string, workingDirectory: string) {
if (!workingDirectory || workingDirectory.trim() === '') {
throw new Error('workingDirectory cannot be empty');
}
if (!existsSync(workingDirectory)) {
throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
}
if (!statSync(workingDirectory).isDirectory()) {
throw new Error(`workingDirectory is not a directory: ${workingDirectory}`);
}
// ... proceed
}
第 2 层:业务逻辑验证
**目的:**确保数据适用于当前操作
function initializeWorkspace(projectDir: string, sessionId: string) {
if (!projectDir) {
throw new Error('projectDir required for workspace initialization');
}
// ... proceed
}
第 3 层:环境保护措施
**目的:**防止在特定上下文中执行危险操作
async function gitInit(directory: string) {
// In tests, refuse git init outside temp directories
if (process.env.NODE_ENV === 'test') {
const normalized = normalize(resolve(directory));
const tmpDir = normalize(resolve(tmpdir()));
if (!normalized.startsWith(tmpDir)) {
throw new Error(
`Refusing git init outside temp dir during tests: ${directory}`
);
}
}
// ... proceed
}
第 4 层:调试检测
**目的:**记录上下文,以便取证
async function gitInit(directory: string) {
const stack = new Error().stack;
logger.debug('About to git init', {
directory,
cwd: process.cwd(),
stack,
});
// ... proceed
}
应用此模式
发现错误时:
- 追踪数据流 - 错误值从何处产生?在哪里使用?
- 梳理所有检查点 - 列出数据经过的每个位置
- 在每一层添加验证 - 入口、业务逻辑、环境、调试
- 测试每一层 - 尝试绕过第 1 层,确认第 2 层能捕获问题
会话示例
错误:空的 projectDir 导致在源代码目录中执行 git init
数据流:
- 测试设置 → 空字符串
Project.create(name, '')WorkspaceManager.createWorkspace('')- 在
process.cwd()中执行git init
添加的四个层级:
- 第 1 层:
Project.create()验证路径非空、存在且可写 - 第 2 层:
WorkspaceManager验证projectDir非空 - 第 3 层:
WorktreeManager在测试中禁止在tmpdir之外执行 git init - 第 4 层:在执行 git init 前记录堆栈跟踪
**结果:**全部 1847 项测试通过,错误不可能重现
关键认识
四个层级缺一不可。测试期间,每一层都捕获了其他层遗漏的错误:
- 不同的代码路径绕过了入口验证
- 模拟绕过了业务逻辑检查
- 不同平台上的边缘情况需要环境保护措施
- 调试日志发现了结构性误用
**不要只停留在一个验证点。**在每一层都添加检查。
安全纵深防御
同样的分层方法也是安全控制的标准模式:绝不会只在单一位置授予信任,因此任何一层中的错误或绕过都无法单独危及系统。每个请求都会在边缘、处理程序和数据层分别进行独立检查。
- 第 1 层(边缘):在边缘(例如 Cloudflare 或 AWS WAF 等 CDN/WAF)进行速率限制和过滤,确保滥用流量无法到达源站。
- 第 2 层(处理程序):在服务端根据会话重新推导授权信息——绝不信任客户端提供的声明,例如请求正文中的
userId。 - 第 3 层(数据):在数据库查询中强制执行所有权不变量,确保即使处理程序存在错误,也无法跨越租户边界。
// Layer 2 — re-derive authz server-side, never trust client claims
app.put('/docs/:id', async (req, res) => {
const user = await verifySession(req.cookies.session); // throws if invalid
// Layer 3 — DB clause re-checks ownership; a handler bug still can't cross tenants
const updated = await db.query(
'UPDATE docs SET title = $1 WHERE id = $2 AND owner_id = $3 RETURNING *',
[req.body.title, req.params.id, user.id]
);
if (!updated.rowCount) return res.status(403).send('Not allowed');
res.json(updated.rows[0]);
});
纵深防御意味着,任何单一层的失效都不足以危及系统。
评论
支持 Markdown