
Defense In Depth
- 34 installs
- 16 repo stars
- Updated November 20, 2025
- jackspace/claudeskillz
Validate data at every layer it passes through - entry, business logic, environment guards, debug logging - to make invalid-data bugs structurally impossible.
About
A validation strategy that adds checks at every layer data passes through rather than a single point. A developer uses it after fixing a data-caused bug to make that class of bug structurally impossible.
- Four validation layers: entry, business logic, environment, debug logging
- Turns 'we fixed the bug' into 'we made the bug impossible'
Defense In Depth by the numbers
- 34 all-time installs (skills.sh)
- Ranked #1,461 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jackspace/claudeskillz --skill defense-in-depthAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 34 |
|---|---|
| repo stars | ★ 16 |
| Last updated | November 20, 2025 |
| Repository | jackspace/claudeskillz ↗ |
What it does
Validate data at every layer it passes through - entry, business logic, environment guards, debug logging - to make invalid-data bugs structurally impossible.
Files
Defense-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.
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
The Four Layers
Layer 1: Entry Point Validation
Purpose: Reject obviously invalid input at API boundary
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
Purpose: Ensure data makes sense for this operation
function initializeWorkspace(projectDir: string, sessionId: string) {
if (!projectDir) {
throw new Error('projectDir required for workspace initialization');
}
// ... proceed
}Layer 3: Environment Guards
Purpose: Prevent dangerous operations in specific contexts
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
Purpose: Capture context for forensics
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:
1. Trace the data flow - Where does bad value originate? Where used? 2. Map all checkpoints - List every point data passes through 3. Add validation at each layer - Entry, business, environment, debug 4. Test each layer - Try to bypass layer 1, verify layer 2 catches it
Example from Session
Bug: Empty projectDir caused git init in source code
Data flow: 1. Test setup → empty string 2. Project.create(name, '') 3. WorkspaceManager.createWorkspace('') 4. git init runs in process.cwd()
Four layers added:
- Layer 1:
Project.create()validates not empty/exists/writable - Layer 2:
WorkspaceManagervalidates projectDir not empty - Layer 3:
WorktreeManagerrefuses git init outside tmpdir in tests - Layer 4: Stack trace logging before git init
Result: All 1847 tests passed, bug impossible to reproduce
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.
{
"sections": {
"Example from Session": "Bug: Empty `projectDir` caused `git init` in source code\r\n\r\n**Data flow:**\r\n1. Test setup → empty string\r\n2. `Project.create(name, '')`\r\n3. `WorkspaceManager.createWorkspace('')`\r\n4. `git init` runs in `process.cwd()`\r\n\r\n**Four layers added:**\r\n- Layer 1: `Project.create()` validates not empty/exists/writable\r\n- Layer 2: `WorkspaceManager` validates projectDir not empty\r\n- Layer 3: `WorktreeManager` refuses git init outside tmpdir in tests\r\n- Layer 4: Stack trace logging before git init\r\n\r\n**Result:** All 1847 tests passed, bug impossible to reproduce",
"Key Insight": "All four layers were necessary. During testing, each layer caught bugs the others missed:\r\n- Different code paths bypassed entry validation\r\n- Mocks bypassed business logic checks\r\n- Edge cases on different platforms needed environment guards\r\n- Debug logging identified structural misuse\r\n\r\n**Don't stop at one validation point.** Add checks at every layer.",
"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.\r\n\r\n**Core principle:** Validate at EVERY layer data passes through. Make the bug structurally impossible.",
"Applying the Pattern": "When you find a bug:\r\n\r\n1. **Trace the data flow** - Where does bad value originate? Where used?\r\n2. **Map all checkpoints** - List every point data passes through\r\n3. **Add validation at each layer** - Entry, business, environment, debug\r\n4. **Test each layer** - Try to bypass layer 1, verify layer 2 catches it",
"The Four Layers": "### Layer 1: Entry Point Validation\r\n**Purpose:** Reject obviously invalid input at API boundary\r\n\r\n```typescript\r\nfunction createProject(name: string, workingDirectory: string) {\r\n if (!workingDirectory || workingDirectory.trim() === '') {\r\n throw new Error('workingDirectory cannot be empty');\r\n }\r\n if (!existsSync(workingDirectory)) {\r\n throw new Error(`workingDirectory does not exist: ${workingDirectory}`);\r\n }\r\n if (!statSync(workingDirectory).isDirectory()) {\r\n throw new Error(`workingDirectory is not a directory: ${workingDirectory}`);\r\n }\r\n // ... proceed\r\n}\r\n```\r\n\r\n### Layer 2: Business Logic Validation\r\n**Purpose:** Ensure data makes sense for this operation\r\n\r\n```typescript\r\nfunction initializeWorkspace(projectDir: string, sessionId: string) {\r\n if (!projectDir) {\r\n throw new Error('projectDir required for workspace initialization');\r\n }\r\n // ... proceed\r\n}\r\n```\r\n\r\n### Layer 3: Environment Guards\r\n**Purpose:** Prevent dangerous operations in specific contexts\r\n\r\n```typescript\r\nasync function gitInit(directory: string) {\r\n // In tests, refuse git init outside temp directories\r\n if (process.env.NODE_ENV === 'test') {\r\n const normalized = normalize(resolve(directory));\r\n const tmpDir = normalize(resolve(tmpdir()));\r\n\r\n if (!normalized.startsWith(tmpDir)) {\r\n throw new Error(\r\n `Refusing git init outside temp dir during tests: ${directory}`\r\n );\r\n }\r\n }\r\n // ... proceed\r\n}\r\n```\r\n\r\n### Layer 4: Debug Instrumentation\r\n**Purpose:** Capture context for forensics\r\n\r\n```typescript\r\nasync function gitInit(directory: string) {\r\n const stack = new Error().stack;\r\n logger.debug('About to git init', {\r\n directory,\r\n cwd: process.cwd(),\r\n stack,\r\n });\r\n // ... proceed\r\n}\r\n```",
"Why Multiple Layers": "Single validation: \"We fixed the bug\"\r\nMultiple layers: \"We made the bug impossible\"\r\n\r\nDifferent layers catch different cases:\r\n- Entry validation catches most bugs\r\n- Business logic catches edge cases\r\n- Environment guards prevent context-specific dangers\r\n- Debug logging helps when other layers fail"
},
"id": "defense-in-depth_obra",
"name": "defense-in-depth",
"description": "Use when invalid data causes failures deep in execution, requiring validation at multiple system layers - validates at every layer data passes through to make bugs structurally impossible"
}---
name: defense-in-depth
description: Use when invalid data causes failures deep in execution, requiring validation at multiple system layers - validates at every layer data passes through to make bugs structurally impossible
---
# Defense-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.
## 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
## The Four Layers
### Layer 1: Entry Point Validation
**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
}
```
### Layer 2: Business Logic Validation
**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
}
```
### Layer 3: Environment Guards
**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
}
```
### Layer 4: Debug Instrumentation
**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
}
```
## Applying the Pattern
When you find a bug:
1. **Trace the data flow** - Where does bad value originate? Where used?
2. **Map all checkpoints** - List every point data passes through
3. **Add validation at each layer** - Entry, business, environment, debug
4. **Test each layer** - Try to bypass layer 1, verify layer 2 catches it
## Example from Session
Bug: Empty `projectDir` caused `git init` in source code
**Data flow:**
1. Test setup → empty string
2. `Project.create(name, '')`
3. `WorkspaceManager.createWorkspace('')`
4. `git init` runs in `process.cwd()`
**Four layers added:**
- Layer 1: `Project.create()` validates not empty/exists/writable
- Layer 2: `WorkspaceManager` validates projectDir not empty
- Layer 3: `WorktreeManager` refuses git init outside tmpdir in tests
- Layer 4: Stack trace logging before git init
**Result:** All 1847 tests passed, bug impossible to reproduce
## 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.