defense-in-depth
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:
- 不同的代码路径绕过了入口验证
- 模拟对象绕过了业务逻辑检查
- 不同平台的边缘情况需要环境防护
- 调试日志识别出了结构性误用
不要仅停留在单一验证点。要在每一层都添加检查。