defense-in-depth-validation
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDefense-in-Depth Validation
纵深防御式验证
Overview
概述
When you fix a bug caused by invalid data, adding validation at one place feels sufficient. But that single check can be bypassed by different code paths, refactoring, or mocks.
Core principle: Validate at EVERY layer data passes through. Make the bug structurally impossible.
当你修复了一个由无效数据引发的bug时,在单一位置添加验证似乎就足够了。但这种单一校验可能会被不同的代码路径、重构操作或模拟数据绕过。
核心原则: 在数据流经的每一层都进行验证,从结构上让bug无产生的可能。
Why Multiple Layers
为何需要多层验证
Single validation: "We fixed the bug"
Multiple layers: "We made the bug impossible"
Different layers catch different cases:
- Entry validation catches most bugs
- Business logic catches edge cases
- Environment guards prevent context-specific dangers
- Debug logging helps when other layers fail
单一验证:"我们修复了这个bug"
多层验证:"我们从根源上杜绝了这个bug"
不同的层级可以捕捉不同的场景:
- 入口验证可拦截绝大多数bug
- 业务逻辑验证可捕捉边缘场景
- 环境防护可避免特定上下文下的风险
- 调试日志可在其他层级失效时提供排查依据
The Four Layers
四个验证层级
Layer 1: Entry Point Validation
层级1:入口点验证
Purpose: Reject obviously invalid input at API boundary
typescript
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
}目标: 在API边界处直接拒绝明显无效的输入
typescript
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
}Layer 2: Business Logic Validation
层级2:业务逻辑验证
Purpose: Ensure data makes sense for this operation
typescript
function initializeWorkspace(projectDir: string, sessionId: string) {
if (!projectDir) {
throw new Error('projectDir required for workspace initialization');
}
// ... proceed
}目标: 确保数据符合当前操作的逻辑要求
typescript
function initializeWorkspace(projectDir: string, sessionId: string) {
if (!projectDir) {
throw new Error('projectDir required for workspace initialization');
}
// ... proceed
}Layer 3: Environment Guards
层级3:环境防护
Purpose: Prevent dangerous operations in specific contexts
typescript
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
}目标: 防止在特定上下文下执行危险操作
typescript
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
}Layer 4: Debug Instrumentation
层级4:调试工具埋点
Purpose: Capture context for forensics
typescript
async function gitInit(directory: string) {
const stack = new Error().stack;
logger.debug('About to git init', {
directory,
cwd: process.cwd(),
stack,
});
// ... proceed
}目标: 捕获上下文信息以用于问题排查
typescript
async function gitInit(directory: string) {
const stack = new Error().stack;
logger.debug('About to git init', {
directory,
cwd: process.cwd(),
stack,
});
// ... proceed
}Applying the Pattern
模式应用步骤
When you find a bug:
- Trace the data flow - Where does bad value originate? Where used?
- Map all checkpoints - List every point data passes through
- Add validation at each layer - Entry, business, environment, debug
- Test each layer - Try to bypass layer 1, verify layer 2 catches it
当你发现一个bug时:
- 追踪数据流 - 错误值的来源在哪里?会被用在哪些地方?
- 梳理所有检查点 - 列出数据流经的每一个节点
- 在每个层级添加验证 - 入口、业务逻辑、环境防护、调试埋点
- 测试每个层级 - 尝试绕过层级1的验证,验证层级2是否能拦截
Example from Session
会话中的示例
Bug: Empty caused in source code
projectDirgit initData flow:
- Test setup → empty string
Project.create(name, '')WorkspaceManager.createWorkspace('')- runs in
git initprocess.cwd()
Four layers added:
- Layer 1: validates not empty/exists/writable
Project.create() - Layer 2: validates projectDir not empty
WorkspaceManager - Layer 3: refuses git init outside tmpdir in tests
WorktreeManager - Layer 4: Stack trace logging before git init
Result: All 1847 tests passed, bug impossible to reproduce
Bug场景:空值导致在源码目录中执行
projectDirgit init数据流:
- 测试设置 → 传入空字符串
Project.create(name, '')WorkspaceManager.createWorkspace('')- 在
git init目录下执行process.cwd()
添加的四个层级验证:
- 层级1:验证路径非空、存在且可写入
Project.create() - 层级2:验证projectDir非空
WorkspaceManager - 层级3:在测试环境下拒绝在临时目录外执行git init
WorktreeManager - 层级4:执行git init前记录堆栈跟踪日志
结果: 全部1847个测试用例通过,该bug无法再复现
Key Insight
关键洞见
All four layers were necessary. During testing, each layer caught bugs the others missed:
- Different code paths bypassed entry validation
- Mocks bypassed business logic checks
- Edge cases on different platforms needed environment guards
- Debug logging identified structural misuse
Don't stop at one validation point. Add checks at every layer.
这四个层级的验证缺一不可。在测试过程中,每个层级都捕捉到了其他层级未覆盖的bug:
- 不同的代码路径绕过了入口验证
- 模拟数据绕过了业务逻辑校验
- 不同平台的边缘场景需要环境防护
- 调试日志发现了结构性误用
不要仅停留在单一验证点。要在每一个层级都添加校验。