skills/defense-in-depth/SKILL.md
Use when a fix validates at only one point in the data flow, when a bug could recur through different code paths, or when the same invalid data could reach internal functions from multiple callers
npx skillsauth add BubbleBuffer/superpawers defense-in-depthInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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 impossible.
digraph when_to_use {
"Fixed a bug?" [shape=diamond];
"Validated at only one point?" [shape=diamond];
"Add validation at every layer" [shape=box];
"Already validated at every layer?" [shape=diamond];
"Single validation is sufficient" [shape=box];
"Fixed a bug?" -> "Validated at only one point?" [label="yes"];
"Validated at only one point?" -> "Add validation at every layer" [label="yes"];
"Validated at only one point?" -> "Already validated at every layer?" [label="no"];
"Already validated at every layer?" -> "Single validation is sufficient" [label="yes"];
"Already validated at every layer?" -> "Add validation at every layer" [label="no - other paths unprotected"];
}
Use when:
Don't use when:
| Layer | Purpose | Example | |-------|---------|---------| | Entry Point | Reject obviously invalid input at API boundary | Check for empty strings, missing paths | | Business Logic | Ensure data makes sense for this operation | Verify dependencies between parameters | | Environment Guards | Prevent dangerous operations in specific contexts | Block filesystem writes outside temp dir in tests | | Debug Instrumentation | Capture context for forensics | Log directory, cwd, stack trace before operation |
Single validation: "We fixed the bug" Multiple layers: "We made the bug impossible"
Different layers catch different cases:
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}`);
}
}
Ensure data makes sense for this operation.
function initializeWorkspace(projectDir: string, sessionId: string) {
if (!projectDir) {
throw new Error('projectDir required for workspace initialization');
}
}
Prevent dangerous operations in specific contexts.
async function gitInit(directory: string) {
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}`
);
}
}
}
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,
});
}
When you find a bug:
All four layers are necessary. During testing, each layer catches bugs the others miss:
Don't stop at one validation point. Add checks at every layer.
| Mistake | Fix | |---------|-----| | Only validating at entry point | Mocks and direct calls bypass entry checks — validate inside too | | Adding guards only in production | Tests run different code paths — add environment guards for test context | | Logging after the operation fails | Log BEFORE the dangerous operation to capture preconditions | | Skipping layers because "it works now" | Each layer catches different failure modes — all four are necessary |
data-ai
Use when a request involves multiple steps or files, or when an approved design must be turned into a detailed implementation plan
development
Use when deciding which SuperPawers skill should govern a new task or workflow step, before taking any other action
development
Use when starting feature work that needs git isolation or before writing committed spec, plan, or code artifacts
development
Use when a task list exists or is being created for multi-step implementation work, whether from a formal plan or an ad-hoc breakdown