Skip to content
Development
Skill

/defense-in-depth-validation

Validate at every layer data passes through to make bugs impossible. Use when invalid data causes failures deep in execution, requiring validation at multiple system layers.

From plugin
claude-skills
241183 skills42 agents62 commands2 MCP

Claude Code

$ npx -y skills add secondsky/claude-skills --skill defense-in-depth-validation --agent claude-code

SKILL.md

defense-in-depth-validation.SKILL.md
name: defense-in-depth-validation
description: Validate at every layer data passes through to make bugs impossible. Use when invalid data causes failures deep in execution, requiring validation at multiple system layers.
metadata:
  version: "1.1.0"
license: MIT

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: `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.

Security defense-in-depth

The same layered approach is the standard pattern for security controls: trust is never granted at a single point, so that a bug or bypass in any one layer cannot by itself compromise the system. Each request is checked independently at the edge, in the handler, and at the data layer.

  • **Layer 1 (edge)**: rate-limit and filter at the edge (CDN/WAF such as

Cloudflare or AWS WAF) so abusive traffic never reaches the origin.

  • **Layer 2 (handler)**: re-derive authorization server-side from the session

— never trust a client-supplied claim like a `userId` in the body.

  • **Layer 3 (data)**: enforce the ownership invariant in the database query so

that even a handler bug cannot cross tenant boundaries.

// 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]);
});

Defense in depth means no single layer's failure is sufficient to compromise the system.

Read more
@secondsky
Ships withclaude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

241183 skills42 agents2 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
241
Star history of secondsky/claude-skills on GitHub, a chart by star-history.com

Other skills on claude-skills.

aceternity-ui

aceternity-ui

100+ animated React components (Aceternity UI) for Next.js with Tailwind. Use for hero sections, parallax, 3D effects, or…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills12d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc13d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react3d252k
@facebook@facebookInstall Skill

Questions about defense-in-depth-validation.

Which coding agents can use defense-in-depth-validation?
defense-in-depth-validation installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.