defense-in-depth
npx machina-cli add skill ed3dai/ed3d-plugins/defense-in-depth --openclawDefense-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.
When to Use
Use when:
- Invalid data caused a bug deep in the call stack
- Data crosses system boundaries (API → service → storage)
- Multiple code paths can reach the same vulnerable code
- Tests mock intermediate layers (bypassing validation)
Don't use when:
- Pure internal function with single caller (validate at caller)
- Data already validated by framework/library you trust
- Adding validation would duplicate identical checks at adjacent layers
The Four Layers
Layer 1: Entry Point Validation
Purpose: Reject invalid input at API/system boundary
function createProject(name: string, workingDirectory: string) {
if (!workingDirectory?.trim()) {
throw new Error('workingDirectory cannot be empty');
}
if (!existsSync(workingDirectory)) {
throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
}
// ... proceed
}
When needed: Always. This is your first line of defense.
Layer 2: Business Logic Validation
Purpose: Ensure data makes sense for this specific operation
function initializeWorkspace(projectDir: string, sessionId: string) {
if (!projectDir) {
throw new Error('projectDir required for workspace initialization');
}
// ... proceed
}
When needed: When business rules differ from entry validation, or when mocks might bypass Layer 1.
Layer 3: Environment Guards
Purpose: Prevent dangerous operations in specific contexts
async function gitInit(directory: string) {
if (process.env.NODE_ENV === 'test') {
const normalized = normalize(resolve(directory));
if (!normalized.startsWith(tmpdir())) {
throw new Error(`Refusing git init outside temp dir in tests: ${directory}`);
}
}
// ... proceed
}
When needed: When operation is destructive/irreversible, especially in test environments.
Layer 4: Debug Instrumentation
Purpose: Capture context for forensics when other layers fail
async function gitInit(directory: string) {
logger.debug('git init', { directory, cwd: process.cwd(), stack: new Error().stack });
// ... proceed
}
When needed: When debugging is difficult, or when you need to trace how bad data arrived.
Decision Heuristic
| Situation | Layers Needed |
|---|---|
| Public API, simple validation | 1 only |
| Data crosses multiple services | 1 + 2 |
| Destructive operations (delete, init, write) | 1 + 2 + 3 |
| Chasing a hard-to-reproduce bug | 1 + 2 + 3 + 4 |
| Tests mock intermediate layers | At minimum: 1 + 3 |
Applying the Pattern
When you find a bug caused by invalid data:
- Trace the data flow - Where does the bad value originate? Where is it used?
- Map checkpoints - List every function/layer the data passes through
- Decide which layers - Use heuristic above
- Add validation - Entry → business → environment → debug
- Test each layer - Verify Layer 2 catches what bypasses Layer 1
Quick Reference
| Layer | Question It Answers | Typical Check |
|---|---|---|
| Entry | Is input valid? | Non-empty, exists, correct type |
| Business | Does it make sense here? | Required for this operation, within bounds |
| Environment | Is this safe in this context? | Not in prod, inside temp dir, etc. |
| Debug | How did we get here? | Log stack, cwd, inputs |
Common Mistakes
| Mistake | Fix |
|---|---|
| One validation point, call it done | Add at least entry + business layers |
| Identical checks at adjacent layers | Make each layer check something different |
| Environment guards only in prod | Add them in test too (prevent test pollution) |
| Skipping debug logging | Add it during the bug hunt, keep it |
| Validation but no useful error message | Include the bad value and expected format |
Key Insight
During testing, each layer catches bugs the others miss:
- Different code paths bypass entry validation
- Mocks bypass business logic checks
- Edge cases need environment guards
- Debug logging identifies structural misuse
Don't stop at one validation point. The bug isn't fixed until it's impossible.
Source
git clone https://github.com/ed3dai/ed3d-plugins/blob/main/plugins/ed3d-house-style/skills/defense-in-depth/SKILL.mdView on GitHub Overview
Defense-in-Depth Validation enforces checks at every layer data passes through to ensure bugs are structurally impossible. Relying on a single validation can be bypassed by refactors or mocks. By validating at Entry Point, Business Logic, Environment Guards, and Debug Instrumentation, you reduce the risk of invalid data causing failures deep in the stack.
How This Skill Works
It implements four layers of validation: Entry Point Validation to reject invalid input at the API boundary; Business Logic Validation to ensure data makes sense for the operation; Environment Guards to prevent dangerous actions in specific contexts; and Debug Instrumentation to capture context for forensics when other layers fail. Each layer throws, blocks, or logs issues, so bypassing earlier checks becomes harder across code paths.
When to Use It
- Invalid data causes a bug deep in the call stack.
- Data crosses system boundaries (API → service → storage).
- Multiple code paths can reach the same vulnerable code.
- Tests mock intermediate layers, bypassing validation.
- Destructive operations (delete, init, write) require cross-layer safeguards.
Quick Start
- Step 1: Trace the data flow and map checkpoints across all layers.
- Step 2: Add validations at Entry Point, Business Logic, Environment, and Debug layers as applicable.
- Step 3: Test across layers to ensure validation catches bypasses and to verify cross-layer coverage.
Best Practices
- Trace the data flow from source to use and identify where bad values originate and are consumed.
- Map checkpoints by listing every function and layer the data passes through.
- Decide which layers to apply using the pattern's heuristic (1–4) and the risk profile.
- Add validations across Entry → Business → Environment → Debug layers.
- Test each layer to verify that Layer 2 catches what bypasses Layer 1 and that failures surface at the intended layer.
Example Use Cases
- Public API validates input at the entry point (non-empty, exists, correct type) before proceeding.
- Business Logic Validation ensures operation-specific rules (e.g., projectDir must exist) are enforced before core actions.
- Environment Guards prevent destructive operations in unsafe contexts (e.g., disallow git init outside temp dirs in tests).
- Debug Instrumentation logs include context (directory, cwd, stack) to aid forensics when data arrives incorrectly.
- Chasing a hard-to-reproduce bug drives adding Layer 1–4 checks and validating that each layer catches bypassed inputs.