---name: my-skilldescription: "Brief one-line description for discovery"allowed-tools: Read Grep Glob---You are an expert [domain] analyzer.## ScopeYou receive code chunks from diffs. Analyze each chunk against the checks below.## Checks### Check 1: [Specific Pattern]**What to look for:**- Concrete code pattern 1- Concrete code pattern 2**Red flags:**- Accessing X without checking Y- Using Z when condition W is not met**Safe patterns:**- Using helper function `foo()` which handles edge cases- Explicit check before operation**Not a bug:**- False positive clarifications---### Check 2: [Another Pattern][Same structure as Check 1]## Report FormatFor each finding:- File path and line number- Which check it matches- One sentence: what is wrong- Why it matters (trigger condition, failure mode)- Suggested fix (only if obvious)### Zero findingsIf no checks fire, report nothing. Silence means the code is clean.## Severity Levels- **high**: Will cause incorrect behavior, data loss, or crash in normal usage- **medium**: Incorrect behavior requiring specific conditions- **low**: Minor issues or style concerns
Let’s build a skill that detects SQL injection vulnerabilities.
1
Define the pattern
We want to catch:
String concatenation in SQL queries
User input passed directly to query functions
Missing parameterization
2
Write the skill
.agents/skills/check-sql-injection/SKILL.md
---name: check-sql-injectiondescription: "Detect SQL injection vulnerabilities from improper query construction"allowed-tools: Read Grep Glob---You are a security-focused code reviewer specialized in SQL injection detection.## ScopeAnalyze code for SQL injection vulnerabilities. Focus on database query construction.## Check: SQL Injection via String Concatenation**Red flags:**- String concatenation or template literals building SQL with user input: `query = "SELECT * FROM users WHERE id = " + userId`- `.format()` or `f-strings` interpolating variables into SQL- User-controlled values in `WHERE`, `ORDER BY`, `LIMIT` clauses without parameterization- Raw SQL execution functions receiving concatenated strings**Safe patterns:**- Parameterized queries: `db.query('SELECT * FROM users WHERE id = ?', [userId])`- ORM methods with bound parameters: `User.findOne({ id: userId })`- Query builders with parameter binding: `knex('users').where('id', userId)`- Hardcoded SQL strings without user input**Not a bug:**- Concatenation of hardcoded SQL fragments (table names, column names from constants)- Logging or error messages containing SQL (not executed)- SQL in comments or documentation## Report FormatFor each vulnerability:- File path and line number- The vulnerable code line- What user input flows into the query- Why parameterization is needed- How to fix (show parameterized version)## Severity- **critical**: User input directly concatenated into executed SQL- **high**: Indirect flow of user input into SQL without validation- **medium**: User input with basic sanitization (still vulnerable)
3
Test the skill
Create test files with vulnerable patterns:
test.ts
// Vulnerable - should triggerconst userId = req.params.id;const query = `SELECT * FROM users WHERE id = ${userId}`;db.query(query);// Safe - should not triggerconst result = db.query('SELECT * FROM users WHERE id = ?', [userId]);
Check if async functions catch promise rejections.Red flags:- Async function without try/catch- Promise chain without .catch()- await without surrounding try/catch
## Confidence Calibration| Level | Criteria | Action ||-------|----------|--------|| HIGH | Pattern traced to specific code, confirmed triggerable | Report || MEDIUM | Pattern present, but context may mitigate | Read more context, then decide || LOW | Vague resemblance | Do NOT report |When in doubt, read more files. Never guess.
For complex checks, guide the agent through steps:
## Step 1: Classify the CodeIdentify which architectural zone(s) the code touches:- SDK layer (`src/sdk/`)- Config layer (`src/config/`)- Output layer (`src/output/`)Only run checks relevant to the touched zones.## Step 2: Run Checks### Check 1: SDK Response Handling(Only if SDK layer is touched)...## Step 3: ReportFor each finding:...
### Check 2: Config Threading**Historical commits:** 8+Config flows through a 3-level merge chain. Breaking this chain causes silent feature failure.**Red flags:**- New config field not threaded through `resolveSkillConfigs()`- Using `||` instead of `??` when 0/false are valid values...
## Step 1: Classify the CodeBefore running checks, identify which zones the code touches:- **SDK layer** (`src/sdk/`): Response parsing, IPC- **CLI layer** (`src/cli/`): Task orchestration, renderingOnly run checks relevant to the touched zones.
# Run on staged changeswarden run --skill my-skill# Run on specific diffgit diff main | warden run --skill my-skill --stdin# Run on specific fileswarden run --skill my-skill --files src/problematic.ts
.agents/skills/my-skill/├── SKILL.md└── fixtures/ ├── vulnerable.ts # Should trigger finding ├── safe.ts # Should not trigger └── edge-case.ts # Tricky case
# Full repo scanwarden run --skill my-skill --schedule# Check recent PRsgh pr list --limit 5 | while read pr; do gh pr diff $pr | warden run --skill my-skill --stdindone
For each finding:- File path and line number- Which check (1-9) it matches- One sentence: what is wrong- Trigger: specific condition that causes failure- Suggested fix (only if clear)### Zero findingsIf no checks fire, report nothing. Do not invent findings.