feat: initial open marketplace with llm-security, config-audit, ultraplan-local
This commit is contained in:
commit
f93d6abdae
380 changed files with 65935 additions and 0 deletions
50
plugins/llm-security/commands/audit.md
Normal file
50
plugins/llm-security/commands/audit.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
name: security:audit
|
||||
description: Full project security audit with OWASP LLM Top 10 assessment, scoring, and remediation plan
|
||||
allowed-tools: Read, Glob, Grep, Bash, Agent
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security audit
|
||||
|
||||
Full security audit — 10 categories, OWASP LLM Top 10 aligned, A-F grade.
|
||||
|
||||
## Step 1: Run Posture Scanner
|
||||
|
||||
Run the deterministic posture scanner first for instant category results:
|
||||
|
||||
```
|
||||
node <this plugin's scanners/posture-scanner.mjs> [cwd]
|
||||
```
|
||||
|
||||
Parse JSON output. Record: grade, risk score, all category statuses, all findings.
|
||||
|
||||
## Step 2: Gather Context
|
||||
|
||||
1. Read `CLAUDE.md` for project name and type
|
||||
2. Glob for: `commands/*.md`, `agents/*.md`, `.mcp.json`, `**/.mcp.json`, `.claude-plugin/plugin.json`
|
||||
3. Determine: has skills/commands? has MCP servers?
|
||||
|
||||
## Step 3: Skill Scan (if commands/agents found)
|
||||
|
||||
Spawn `subagent_type: "llm-security:skill-scanner-agent"`, `model: "sonnet"`:
|
||||
|
||||
> Scan all commands/ and agents/ at [cwd].
|
||||
> Read: \<plugin-root\>/knowledge/skill-threat-patterns.md
|
||||
> Return findings: file, issue, severity, OWASP ref.
|
||||
|
||||
## Step 4: MCP Scan (if MCP servers found)
|
||||
|
||||
After skill scan, spawn `subagent_type: "llm-security:mcp-scanner-agent"`, `model: "sonnet"`:
|
||||
|
||||
> Audit MCP configs at [cwd]. Read: \<plugin-root\>/knowledge/mcp-threat-patterns.md
|
||||
> Return trust table and findings with severity.
|
||||
|
||||
## Step 5: Generate Report
|
||||
|
||||
Merge posture scanner JSON + agent findings. Use the posture scanner's grade as the baseline.
|
||||
Recalculate `risk_score = min(100, critical*25 + high*10 + medium*4 + low*1)` including agent findings.
|
||||
|
||||
Output: Risk Dashboard, Executive Summary, 10 Category Sections (use scanner evidence + agent narrative), Summary Table, Action Items (IMMEDIATE → HIGH → MEDIUM).
|
||||
|
||||
Close with top 2-3 action items. If grade C or lower: suggest `/security threat-model`.
|
||||
61
plugins/llm-security/commands/clean.md
Normal file
61
plugins/llm-security/commands/clean.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
name: security:clean
|
||||
description: Scan and remediate security findings — auto-fixes deterministic issues, confirms semi-auto with user, reports manual findings
|
||||
allowed-tools: Read, Glob, Grep, Bash, Write, Edit, Agent, AskUserQuestion
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security clean [path] [--dry-run]
|
||||
|
||||
Scan, classify findings by remediability, auto-fix deterministic issues, propose semi-auto fixes, report manual. Goal: `/security scan` yields zero findings after clean.
|
||||
|
||||
## Step 1: Setup
|
||||
|
||||
- Parse `$ARGUMENTS`: extract path (default `.`), `--dry-run` flag. Resolve to absolute.
|
||||
- Plugin root = parent of this `commands/` folder.
|
||||
- Unless dry-run: create backup via `node <plugin-root>/scanners/lib/fs-utils.mjs backup "<target>"`. Record backup path.
|
||||
|
||||
## Step 2: Pre-Clean Scan
|
||||
|
||||
```bash
|
||||
node <plugin-root>/scanners/lib/fs-utils.mjs tmppath clean-findings.json
|
||||
node <plugin-root>/scanners/scan-orchestrator.mjs "<target>" --output-file "<findings_file>"
|
||||
```
|
||||
|
||||
Show banner: Verdict, Risk Score, Finding counts. If 0 findings → stop.
|
||||
|
||||
## Step 3: Auto-Fix
|
||||
|
||||
```bash
|
||||
node <plugin-root>/scanners/auto-cleaner.mjs "<target>" --findings "<findings_file>" [--dry-run]
|
||||
```
|
||||
|
||||
Report: Applied/Skipped/Failed counts + list of fixes.
|
||||
|
||||
## Step 4: Semi-Auto Proposals
|
||||
|
||||
Collect `semi_auto` findings from auto-cleaner output. If any, spawn `subagent_type: "llm-security:cleaner-agent"`, `model: "sonnet"`:
|
||||
|
||||
> Here are semi-auto findings: \<JSON\>. Target: \<target\>.
|
||||
> Read: \<plugin-root\>/knowledge/secrets-patterns.md
|
||||
> Return remediation proposals as JSON.
|
||||
|
||||
Present each proposal group via AskUserQuestion: "Apply all" / "Review individually" / "Skip". Apply approved fixes with Edit tool. Skip if dry-run.
|
||||
|
||||
## Step 5: LLM Threat Scan
|
||||
|
||||
Spawn `subagent_type: "llm-security:skill-scanner-agent"`, `model: "sonnet"`:
|
||||
|
||||
> Scan target: \<target\>. Read: \<plugin-root\>/knowledge/skill-threat-patterns.md, \<plugin-root\>/knowledge/secrets-patterns.md
|
||||
> Return findings with severity, category, file, line, remediation.
|
||||
|
||||
Auto-fix deterministic LLM findings (injection comments, spoofed headers, exfil URLs). Present semi-auto via AskUserQuestion. Report manual findings.
|
||||
|
||||
## Step 6: Validate + Re-Scan
|
||||
|
||||
Validate modified files (JSON parse, frontmatter, `node --check`). Restore from backup on failure. Re-run orchestrator to measure improvement.
|
||||
|
||||
## Step 7: Report
|
||||
|
||||
Output: Pre/post comparison, all fix summaries, remaining manual findings, rollback instructions.
|
||||
- Dry-run: show "DRY-RUN" mode, list proposed changes without applying.
|
||||
61
plugins/llm-security/commands/dashboard.md
Normal file
61
plugins/llm-security/commands/dashboard.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
name: security:dashboard
|
||||
description: Cross-project security dashboard — machine-wide posture overview with per-project grades
|
||||
allowed-tools: Read, Glob, Grep, Bash
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security dashboard
|
||||
|
||||
Machine-wide security dashboard. Discovers all Claude Code projects, runs posture-scanner on each, shows aggregated overview.
|
||||
|
||||
## Step 1: Run Dashboard Aggregator
|
||||
|
||||
Run the aggregator (uses 24h cache by default):
|
||||
|
||||
```
|
||||
node <this plugin's scanners/dashboard-aggregator.mjs>
|
||||
```
|
||||
|
||||
If user specified `--no-cache` or `--fresh`, add `--no-cache` flag.
|
||||
|
||||
Parse the JSON output. The result contains:
|
||||
- `meta.scanner`, `meta.version`, `meta.timestamp`, `meta.from_cache`
|
||||
- `machine.grade` (weakest link), `machine.projects_scanned`, `machine.total_findings`, `machine.counts`
|
||||
- `projects[]` with path, display_name, grade, risk_score, risk_band, worst_category, worst_status, findings_count, counts
|
||||
- `errors[]` with path, display_name, error
|
||||
|
||||
## Step 2: Format Dashboard
|
||||
|
||||
Present the results:
|
||||
|
||||
```
|
||||
# Security Dashboard
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Machine Grade** | [A-F] (weakest link) |
|
||||
| **Projects Scanned** | [N] |
|
||||
| **Total Findings** | [N] |
|
||||
| **Scan Time** | [N]ms |
|
||||
| **Cache** | [Fresh scan / Cached (age)] |
|
||||
|
||||
## Project Overview
|
||||
|
||||
| Project | Grade | Risk | Worst Category | Findings |
|
||||
|---------|-------|------|----------------|----------|
|
||||
[one row per project, sorted by grade (worst first)]
|
||||
|
||||
## Errors
|
||||
|
||||
[List any projects that failed to scan, if any]
|
||||
```
|
||||
|
||||
Sort the project table by grade (F first, A last), then by risk score descending.
|
||||
|
||||
## Step 3: Recommendations
|
||||
|
||||
- If machine grade is A/B: "Machine posture is solid. Re-run after major changes or new plugin installs."
|
||||
- If machine grade is C: "Some projects need attention. Run `/security posture` in the worst-graded project."
|
||||
- If machine grade is D/F: "Significant exposure. Run `/security audit` in projects graded D/F."
|
||||
- If from_cache: "Results cached. Run `/security dashboard --fresh` for a live scan."
|
||||
42
plugins/llm-security/commands/deep-scan.md
Normal file
42
plugins/llm-security/commands/deep-scan.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
name: security:deep-scan
|
||||
description: Run deterministic deep-scan — 9 Node.js scanners for Unicode attacks, entropy analysis, permission mapping, dependency auditing, taint tracing, git forensics, network mapping, memory poisoning, and toxic flow analysis
|
||||
allowed-tools: Read, Glob, Grep, Bash, Agent
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security deep-scan [path]
|
||||
|
||||
9 deterministic Node.js scanners — entropy, Unicode, typosquatting, git forensics, taint tracing, dep audit, network mapping, memory poisoning, toxic flow analysis.
|
||||
|
||||
## Step 1: Setup
|
||||
|
||||
- `$ARGUMENTS` empty → target = cwd. Otherwise target = `$ARGUMENTS` (strip `--deep`).
|
||||
- Plugin root = parent of this `commands/` folder.
|
||||
- Get temp path: `node -p "require('path').join(require('os').tmpdir(), 'deep-scan-results.json')"`
|
||||
|
||||
## Step 2: Run Orchestrator
|
||||
|
||||
```bash
|
||||
node <plugin-root>/scanners/scan-orchestrator.mjs "<target>" --output-file "<results_file>"
|
||||
```
|
||||
|
||||
Exit 0=ALLOW, 1=WARNING, 2=BLOCK. Stdout = compact aggregate JSON. Full results in file.
|
||||
|
||||
## Step 3: Show Banner
|
||||
|
||||
```
|
||||
## Deep Scan: [VERDICT]
|
||||
Risk Score: X/100 | Findings: XC XH XM XL XI
|
||||
Scanners: X ok, X error, X skipped
|
||||
```
|
||||
|
||||
## Step 4: Synthesize Report
|
||||
|
||||
Spawn `subagent_type: "llm-security:deep-scan-synthesizer-agent"`, `model: "sonnet"`:
|
||||
|
||||
> Read scan results from: \<results_file\>
|
||||
> Read: \<plugin-root\>/knowledge/mitigation-matrix.md
|
||||
> Produce complete report with actionable insights. Don't pad.
|
||||
|
||||
Output the synthesizer's report. If it fails, show banner + CRITICAL/HIGH findings from JSON.
|
||||
98
plugins/llm-security/commands/diff.md
Normal file
98
plugins/llm-security/commands/diff.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
---
|
||||
name: security:diff
|
||||
description: Compare scan results against a stored baseline — shows new, resolved, unchanged, and moved findings
|
||||
allowed-tools: Bash, Read, AskUserQuestion
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security diff [path]
|
||||
|
||||
Run a deterministic deep scan and compare results against a stored baseline. Shows what changed since the last saved scan.
|
||||
|
||||
## Step 1: Check for Existing Baseline
|
||||
|
||||
Determine plugin root (parent of this `commands/` folder) and target path from `$ARGUMENTS` (default `.`).
|
||||
|
||||
Check if a baseline already exists:
|
||||
|
||||
```bash
|
||||
ls -la <plugin-root>/reports/baselines/ 2>/dev/null
|
||||
```
|
||||
|
||||
If baseline files exist for the target, inform the user:
|
||||
|
||||
> A baseline already exists. Running `/security diff` will overwrite it with new results.
|
||||
|
||||
Use AskUserQuestion to ask: "Overwrite existing baseline and run diff? (The previous baseline will be replaced.)"
|
||||
|
||||
If the user declines, exit without scanning. If the user confirms (or no baseline exists yet), proceed to Step 2.
|
||||
|
||||
## Step 2: Run Scan with Baseline Comparison
|
||||
|
||||
```bash
|
||||
node <plugin-root>/scanners/scan-orchestrator.mjs "<target>" --baseline --save-baseline
|
||||
```
|
||||
|
||||
Parse stdout JSON. The scan runs all 9 scanners, diffs against any existing baseline, then saves the new results as the current baseline.
|
||||
|
||||
If no baseline exists yet (`diff` is `null` in output), this is a first run — report that a baseline has been created and show the current scan summary instead of a diff.
|
||||
|
||||
## Step 3: Display Results
|
||||
|
||||
### First run (no prior baseline)
|
||||
|
||||
```
|
||||
## Baseline Created
|
||||
|
||||
No prior baseline found. Current scan saved as baseline.
|
||||
|
||||
**Findings:** XC XH XM XL XI | **Risk Score:** X/100 | **Verdict:** ALLOW/WARNING/BLOCK
|
||||
|
||||
Run `/security diff` again after making changes to see the delta.
|
||||
```
|
||||
|
||||
### Subsequent runs (diff available)
|
||||
|
||||
```
|
||||
## Security Diff: <target>
|
||||
|
||||
**Baseline:** <baseline_timestamp> → **Current:** <now>
|
||||
|
||||
### Summary
|
||||
| Category | Count |
|
||||
|----------|-------|
|
||||
| New | X |
|
||||
| Resolved | X |
|
||||
| Moved | X |
|
||||
| Unchanged| X |
|
||||
```
|
||||
|
||||
For **New** findings (sorted critical → info):
|
||||
|
||||
```
|
||||
### New Findings (X)
|
||||
| # | Severity | Scanner | Title | File | OWASP |
|
||||
```
|
||||
|
||||
For **Resolved** findings:
|
||||
|
||||
```
|
||||
### Resolved Findings (X)
|
||||
| # | Severity | Scanner | Title | File | OWASP |
|
||||
```
|
||||
|
||||
For **Moved** findings (only if count > 0):
|
||||
|
||||
```
|
||||
### Moved Findings (X)
|
||||
| # | Severity | Scanner | Title | File | Previous Location |
|
||||
```
|
||||
|
||||
Omit Unchanged findings from the output — they add noise. Mention count in summary only.
|
||||
|
||||
## Step 4: Advisory
|
||||
|
||||
- If new CRITICAL/HIGH findings: "**Action required:** X new critical/high findings since baseline."
|
||||
- If resolved > new: "**Improving:** more findings resolved than introduced."
|
||||
- If new > 0 and resolved == 0: "**Regression:** X new findings, none resolved."
|
||||
- If new == 0 and resolved == 0: "**Stable:** no changes since baseline."
|
||||
72
plugins/llm-security/commands/harden.md
Normal file
72
plugins/llm-security/commands/harden.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
name: security:harden
|
||||
description: Generate Grade A security configuration — settings.json, CLAUDE.md security section, .gitignore additions
|
||||
allowed-tools: Read, Glob, Grep, Bash, Write, Edit, AskUserQuestion
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security harden [path] [--apply] [--dry-run]
|
||||
|
||||
Generate reference security configuration to achieve Grade A posture. Runs posture scanner, identifies gaps, generates config to close them.
|
||||
|
||||
## Step 1: Generate
|
||||
|
||||
Run the reference configuration generator:
|
||||
|
||||
```
|
||||
node <this plugin's scanners/reference-config-generator.mjs> [target-path or cwd] [--apply]
|
||||
```
|
||||
|
||||
Default is `--dry-run` (show JSON output, do not write files).
|
||||
|
||||
Parse the JSON output. The result contains:
|
||||
- `projectType`: plugin, monorepo, or standalone
|
||||
- `posture`: current grade, pass_rate, pass/partial/fail counts
|
||||
- `recommendations[]`: file, action (create/merge/append/none), content, category
|
||||
- `summary`: total, actionable, creates, merges, appends
|
||||
|
||||
## Step 2: Present Results
|
||||
|
||||
```
|
||||
# Security Harden — [project name]
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Current Grade** | [grade] |
|
||||
| **Project Type** | [type] |
|
||||
| **Recommendations** | [actionable]/[total] |
|
||||
|
||||
## Recommendations
|
||||
|
||||
[For each recommendation with action != 'none':]
|
||||
### [N]. [category] — [file]
|
||||
- **Action:** [create/merge/append]
|
||||
- **Content preview:** [first 3 lines or summary]
|
||||
```
|
||||
|
||||
## Step 3: Apply (if --apply or user confirms)
|
||||
|
||||
If `$ARGUMENTS` contains `--apply`, the generator already wrote files. Report what was changed.
|
||||
|
||||
If `$ARGUMENTS` is `--dry-run` or empty, ask the user:
|
||||
|
||||
> "Apply these [N] changes? This will create a backup first."
|
||||
|
||||
If confirmed, re-run with `--apply`. Report backup location and files written.
|
||||
|
||||
## Step 4: Post-Apply Verification
|
||||
|
||||
After applying, re-run posture scanner to verify improvement:
|
||||
|
||||
```
|
||||
node <this plugin's scanners/posture-scanner.mjs> [target-path]
|
||||
```
|
||||
|
||||
Report: "Grade improved from [old] to [new]." or "Grade unchanged at [grade]."
|
||||
|
||||
If Grade A not achieved, explain remaining gaps (likely hook-related, which require manual setup or plugin installation).
|
||||
|
||||
## Step 5: Closing
|
||||
|
||||
- Grade A: "Configuration hardened. All posture checks pass."
|
||||
- Below A: "Configuration improved. Remaining gaps require [hooks/manual setup]. Run `/security posture` for details."
|
||||
47
plugins/llm-security/commands/mcp-audit.md
Normal file
47
plugins/llm-security/commands/mcp-audit.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
name: security:mcp-audit
|
||||
description: Audit all installed MCP server configurations for security risks, trust verification, and permission analysis
|
||||
allowed-tools: Read, Glob, Grep, Agent, Bash
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security mcp-audit [--live]
|
||||
|
||||
Full MCP server security audit — project-level and global. Add `--live` to also connect to running servers and scan live tool descriptions.
|
||||
|
||||
## Step 0: Parse Flags
|
||||
|
||||
If `$ARGUMENTS` contains `--live`, strip it and set `run_live_inspection = true`.
|
||||
|
||||
## Step 1: Discovery
|
||||
|
||||
Read MCP configs from: `.mcp.json`, `.claude/settings.json`, `claude_desktop_config.json`, `~/.claude/settings.json`, `~/.claude/mcp.json`, `~/.config/claude/mcp.json`.
|
||||
|
||||
For each server extract: name, transport (stdio/sse), command+args or URL, env var names (redact values), source origin. Report total count.
|
||||
|
||||
## Step 2: Scan
|
||||
|
||||
Spawn `subagent_type: "llm-security:mcp-scanner-agent"`, `model: "sonnet"`:
|
||||
|
||||
> Full MCP audit. Read: \<plugin-root\>/knowledge/mcp-threat-patterns.md
|
||||
> Execute all 5 phases per server (tool descriptions, source code, dependencies, config, rug pull detection).
|
||||
> Servers: \<discovered server list with name, type, command, source, env vars\>
|
||||
> Return per-server trust rating + findings.
|
||||
|
||||
## Step 3: Report
|
||||
|
||||
Output: MCP Landscape Summary table (server, source, transport, trust rating, finding counts).
|
||||
Overall risk: Low (all trusted) / Medium (cautious+high) / High (untrusted) / Critical (dangerous).
|
||||
Group servers: Keep / Review / Remove immediately.
|
||||
|
||||
## Step 4: Live Inspection (only if `--live`)
|
||||
|
||||
Run: `node <plugin-root>/scanners/mcp-live-inspect.mjs "<cwd>"`
|
||||
|
||||
Parse JSON output. Append a **Live Inspection Results** section:
|
||||
|
||||
- Contact status per server (contacted / timed-out / skipped / failed)
|
||||
- Live injection findings (sorted critical → info)
|
||||
- Tool shadowing across servers
|
||||
|
||||
**Cross-reference escalation:** If a server was rated "Untrusted" or "Dangerous" in Step 2 AND has live injection findings → escalate to CRITICAL priority in the final report and highlight as "Confirmed active threat (static + live)".
|
||||
54
plugins/llm-security/commands/mcp-inspect.md
Normal file
54
plugins/llm-security/commands/mcp-inspect.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
name: security:mcp-inspect
|
||||
description: Connect to running MCP servers and scan live tool descriptions for injection, shadowing, and drift
|
||||
allowed-tools: Bash, Read
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security mcp-inspect [path]
|
||||
|
||||
Live MCP runtime inspection — connects to each configured MCP stdio server via JSON-RPC 2.0, fetches tool/prompt/resource lists, and scans descriptions for injection patterns and tool shadowing.
|
||||
|
||||
## Step 1: Run Scanner
|
||||
|
||||
Determine plugin root (parent of this `commands/` folder) and target path from `$ARGUMENTS` (default `.`).
|
||||
|
||||
```bash
|
||||
node <plugin-root>/scanners/mcp-live-inspect.mjs "<target>"
|
||||
```
|
||||
|
||||
Parse stdout as JSON. If exit code is non-zero and no JSON output, show the error and STOP.
|
||||
|
||||
## Step 2: Report
|
||||
|
||||
Display:
|
||||
|
||||
```
|
||||
## MCP Live Inspection: <VERDICT>
|
||||
|
||||
**Servers:** <discovered> discovered | <contacted> contacted | <timed_out> timed out | <skipped_sse> SSE skipped | <failed> failed
|
||||
|
||||
### Server Details
|
||||
| Server | Status | Tools | Prompts | Resources | Time |
|
||||
```
|
||||
|
||||
For each finding (sorted critical → info):
|
||||
|
||||
```
|
||||
### Findings (<count>)
|
||||
|
||||
| # | Severity | Title | OWASP | Recommendation |
|
||||
```
|
||||
|
||||
If zero findings: "No injection, shadowing, or drift detected across N servers."
|
||||
|
||||
## Step 3: Advisory
|
||||
|
||||
- If `servers_timed_out > 0`: "N servers timed out (10s). Ensure they can start independently — check command, env vars, and args."
|
||||
- If `servers_skipped_sse > 0`: "N SSE servers skipped — live inspection requires stdio transport."
|
||||
- If `servers_failed > 0`: "N servers failed to start. Verify the command path exists and is executable."
|
||||
- If `servers_discovered == 0`: "No MCP servers found in config locations. Check .mcp.json, .claude/settings.json, or ~/.claude/settings.json."
|
||||
|
||||
## Step 4: Combined Use
|
||||
|
||||
Mention: "For combined static + live analysis, use `/security mcp-audit --live`."
|
||||
64
plugins/llm-security/commands/plugin-audit.md
Normal file
64
plugins/llm-security/commands/plugin-audit.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
name: security:plugin-audit
|
||||
description: Audit a Claude Code plugin for security risks, permission analysis, and trust assessment before installation
|
||||
allowed-tools: Read, Glob, Grep, Bash, Agent
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security plugin-audit [path|url]
|
||||
|
||||
Audit a Claude Code plugin for security before installation. Accepts local paths or GitHub URLs.
|
||||
|
||||
## Step 1: Resolve Target
|
||||
|
||||
- If `$ARGUMENTS` contains `--branch <name>` → strip it, set `branch = <name>`
|
||||
- If `$ARGUMENTS` starts with `https://github.com/` or `git@github.com:` →
|
||||
Run: `node <plugin-root>/scanners/lib/git-clone.mjs clone "<url>" [--branch <branch>]`
|
||||
If exit code != 0 → show error to user and **STOP**
|
||||
Set `clone_path` = stdout (trimmed), `target = clone_path`
|
||||
Set `remote_url = <url>` for display
|
||||
- Else if `$ARGUMENTS` is non-empty → `target = $ARGUMENTS`, `clone_path = null`
|
||||
- Else → `target = "."`, `clone_path = null`
|
||||
- Verify `.claude-plugin/plugin.json` exists at `<target>`. If not and `clone_path != null` → cleanup clone_path first, then tell user this is not a plugin directory and **STOP**. If not and local → tell user and **STOP**.
|
||||
|
||||
## Step 1.5: Pre-extraction (remote audits only)
|
||||
|
||||
If `clone_path != null`:
|
||||
Get temp path: `node <plugin-root>/scanners/lib/fs-utils.mjs tmppath "plugin-extract.json"`
|
||||
Run: `node <plugin-root>/scanners/content-extractor.mjs "<target>" --output-file "<evidence_file>"`
|
||||
If exit code != 0 → set `evidence_file = null` (fall back to direct scan)
|
||||
|
||||
## Step 2: Inventory
|
||||
|
||||
Read plugin.json (name, version, auto_discover). Glob for commands, agents, hooks, skills, knowledge. Build permission matrix from all `allowed-tools` and `tools` declarations. Flag: Bash access, Bash+Write combo, Task (sub-agent spawning), opus for trivial tasks.
|
||||
|
||||
## Step 3: Analyze Hooks
|
||||
|
||||
If `hooks/hooks.json` exists: parse events, read scripts, classify (block/warn/modify). Flag: state modification, network calls, non-CLAUDE env vars, SessionStart hooks.
|
||||
|
||||
## Step 4: Scan Content
|
||||
|
||||
Spawn `subagent_type: "llm-security:skill-scanner-agent"`, `model: "sonnet"`:
|
||||
|
||||
If `evidence_file` is set:
|
||||
> EVIDENCE-PACKAGE MODE. Read: \<evidence_file\>
|
||||
> Read: \<plugin-root\>/knowledge/skill-threat-patterns.md
|
||||
> Analyze all sections. DO NOT use Read/Glob/Grep on the target directory.
|
||||
> Check all 7 threat categories. Return findings: file, severity, OWASP ref.
|
||||
|
||||
Otherwise:
|
||||
> Scan plugin at \<path\>: commands/*.md, agents/*.md, hooks/scripts/*, skills/*/SKILL.md, knowledge/**/*.md.
|
||||
> Read: \<plugin-root\>/knowledge/skill-threat-patterns.md
|
||||
> Check all 7 threat categories. Return findings: file, severity, OWASP ref.
|
||||
|
||||
## Step 5: Report
|
||||
|
||||
Output: Plugin metadata, component inventory, permission matrix, hook analysis, security findings, trust verdict.
|
||||
|
||||
Verdict: **Install** (0 critical/high, transparent hooks) | **Review** (high findings or unclear permissions) | **Do Not Install** (critical, exfiltration, persistence, or hidden instructions).
|
||||
|
||||
## Step 6: Cleanup (only if remote)
|
||||
|
||||
If `clone_path != null`:
|
||||
Run: `node <plugin-root>/scanners/lib/git-clone.mjs cleanup "<clone_path>"`
|
||||
If cleanup fails → warn: "Could not remove temp dir <clone_path> — remove manually."
|
||||
60
plugins/llm-security/commands/posture.md
Normal file
60
plugins/llm-security/commands/posture.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
name: security:posture
|
||||
description: Quick security posture assessment — scorecard with grade, coverage status, and top recommendations
|
||||
allowed-tools: Read, Glob, Grep, Bash
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security posture
|
||||
|
||||
Quick security scorecard — grade, coverage, top recommendations. Deterministic scanner, <2 sec.
|
||||
|
||||
## Step 1: Run Scanner
|
||||
|
||||
Run the deterministic posture scanner:
|
||||
|
||||
```
|
||||
node <this plugin's scanners/posture-scanner.mjs> [target-path or cwd]
|
||||
```
|
||||
|
||||
Parse the JSON output. The result contains:
|
||||
- `scoring.grade` (A-F), `scoring.pass_rate`, `scoring.pass/partial/fail/na`
|
||||
- `risk.score` (0-100), `risk.band`, `risk.verdict`
|
||||
- `categories[]` with id, name, status, findings_count, evidence
|
||||
- `findings[]` with severity, title, description, owasp, recommendation
|
||||
- `counts` with critical/high/medium/low/info
|
||||
|
||||
## Step 2: Format Scorecard
|
||||
|
||||
Present the results as a scorecard:
|
||||
|
||||
```
|
||||
# Security Posture — [project name]
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Grade** | [A-F] |
|
||||
| **Risk Score** | [N]/100 ([band]) |
|
||||
| **Verdict** | [verdict] |
|
||||
| **Duration** | [N]ms |
|
||||
|
||||
## Category Scorecard
|
||||
|
||||
| # | Category | Status | Findings |
|
||||
|---|----------|--------|----------|
|
||||
[one row per category, status as PASS/PARTIAL/FAIL/N-A]
|
||||
|
||||
## Top Findings
|
||||
|
||||
[List critical and high findings with title, file, and recommendation]
|
||||
|
||||
## Quick Wins
|
||||
|
||||
[List low-effort fixes from findings]
|
||||
```
|
||||
|
||||
## Step 3: Closing
|
||||
|
||||
- Grade A/B: "Posture solid. Re-run after major changes."
|
||||
- Grade C: "Run `/security audit` for detailed findings."
|
||||
- Grade D/F: "Significant exposure. Run `/security audit` before production use."
|
||||
101
plugins/llm-security/commands/pre-deploy.md
Normal file
101
plugins/llm-security/commands/pre-deploy.md
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
---
|
||||
name: security:pre-deploy
|
||||
description: Pre-deployment security checklist — verify enterprise controls, compliance, and production readiness
|
||||
allowed-tools: Read, Glob, Grep, AskUserQuestion
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security pre-deploy
|
||||
|
||||
Running pre-deployment security checklist...
|
||||
|
||||
## Automated Checks
|
||||
|
||||
Run each check and record status (PASS / FAIL / WARN / N/A).
|
||||
|
||||
### 1 — Deny-first permissions
|
||||
Read `.claude/settings.json` and `~/.claude/settings.json`. Look for `"permissions"` block with a deny-first or allowlist-only policy (e.g., `"defaultMode": "allowList"` or explicit deny rules). Status: PASS if deny-first found, WARN if not configured, FAIL if allow-all detected.
|
||||
|
||||
### 2 — Secrets hook active
|
||||
Read `hooks/hooks.json` (or `.claude/hooks.json`). Check for a `PreToolUse` hook matching `Edit|Write` that references `pre-edit-secrets`. Status: PASS if found, FAIL if absent.
|
||||
|
||||
### 3 — Path guard active
|
||||
Same hooks.json or global `~/.claude/settings.json` hooks. Check for a `PreToolUse` hook matching `Write` or `Edit|Write` that references `pre-write-pathguard`. Status: PASS if found locally or globally, FAIL if absent in both.
|
||||
|
||||
### 4 — Destructive command guard
|
||||
Same hooks.json. Check for a `PreToolUse` hook matching `Bash` that references `pre-bash-destructive` or equivalent firewall script. Status: PASS if found, WARN if absent.
|
||||
|
||||
### 5 — MCP servers verified
|
||||
Read `.mcp.json` if it exists. For each server listed, check whether it is a known/trusted server (Linear, MS Learn, Tavily, GitHub, etc.) vs. unknown third-party. Flag any unknown servers. Status: PASS if all known, WARN if unknown servers present, N/A if no .mcp.json.
|
||||
|
||||
### 6 — No hardcoded secrets
|
||||
Grep source files (excluding `node_modules`, `.git`, `*.md`) for common secret patterns: `API_KEY`, `api_key`, `secret`, `password`, `token`, `bearer`, `sk-`, `-----BEGIN`. Status: PASS if no hits, FAIL if hits found.
|
||||
|
||||
### 7 — .gitignore covers secrets
|
||||
Read `.gitignore`. Check for entries covering `.env`, `.env.*`, `credentials`, `*.key`, `*.pem`, `secrets*`. Status: PASS if at least 3 of these patterns present, WARN if partial, FAIL if absent.
|
||||
|
||||
### 8 — CLAUDE.md has security section
|
||||
Read `CLAUDE.md`. Check for a section or heading mentioning security, secrets, hooks, or permissions. Status: PASS if found, WARN if absent.
|
||||
|
||||
### 9 — Sandbox enabled
|
||||
Read settings files. Check for `"sandbox": true` or sandbox-related configuration. Status: PASS if enabled, WARN if not configured (sandbox is opt-in).
|
||||
|
||||
### 10 — Audit logging configured
|
||||
Check hooks.json for any `Stop` or `PostToolUse` hooks that write audit logs, or check settings for audit log paths. Status: PASS if found, WARN if absent.
|
||||
|
||||
## Manual Verification
|
||||
|
||||
Ask the user these questions using AskUserQuestion (one at a time):
|
||||
|
||||
1. "Is this project deployed under an Anthropic Enterprise plan? (SSO, SCIM, and audit logging are enterprise-only controls.)"
|
||||
2. "Has a DPIA (Data Protection Impact Assessment) been completed for this AI solution?"
|
||||
3. "Is there a documented incident response plan for AI failures or security incidents?"
|
||||
|
||||
Record answers and include in the report.
|
||||
|
||||
## Report
|
||||
|
||||
Generate the report using `templates/unified-report.md` (ANALYSIS_TYPE: pre-deploy) as the format reference. Structure:
|
||||
|
||||
```
|
||||
## Pre-Deployment Security Checklist
|
||||
|
||||
Passed: X/10 automated checks
|
||||
|
||||
| # | Check | Status | Detail |
|
||||
|---|--------------------------|--------|---------------------------------|
|
||||
| 1 | Deny-first permissions | ... | ... |
|
||||
| 2 | Secrets hook | ... | ... |
|
||||
| 3 | Path guard | ... | ... |
|
||||
| 4 | Destructive cmd guard | ... | ... |
|
||||
| 5 | MCP servers verified | ... | ... |
|
||||
| 6 | No hardcoded secrets | ... | ... |
|
||||
| 7 | .gitignore covers secrets| ... | ... |
|
||||
| 8 | CLAUDE.md security docs | ... | ... |
|
||||
| 9 | Sandbox enabled | ... | ... |
|
||||
|10 | Audit logging | ... | ... |
|
||||
|
||||
## Manual Verification
|
||||
|
||||
- [ ] Enterprise plan: [user answer]
|
||||
- [ ] DPIA completed: [user answer]
|
||||
- [ ] Incident response plan: [user answer]
|
||||
|
||||
## Recommendations
|
||||
|
||||
[List FAIL items first, then WARN items, with specific remediation steps for each.]
|
||||
```
|
||||
|
||||
## Verdict
|
||||
|
||||
Map the pass count to a risk band and verdict:
|
||||
|
||||
| Pass Count | Risk Band | Verdict |
|
||||
|-----------|-----------|---------|
|
||||
| 10/10 | Low | Ready for deployment — all automated checks passed. |
|
||||
| 8-9/10 | Medium | Nearly ready — address the remaining items before deploying. |
|
||||
| 6-7/10 | High | Significant gaps — resolve FAIL items before deployment. |
|
||||
| 4-5/10 | Critical | Not ready — major security gaps. Immediate remediation needed. |
|
||||
| 0-3/10 | Extreme | Critical risk — deployment blocked until fundamental controls are in place. |
|
||||
|
||||
State the verdict and risk band clearly at the end of the report.
|
||||
95
plugins/llm-security/commands/red-team.md
Normal file
95
plugins/llm-security/commands/red-team.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
name: llm-security:red-team
|
||||
description: Attack simulation — test hook defenses with crafted payloads
|
||||
allowed-tools: Bash, Read
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# Red Team — Attack Simulation
|
||||
|
||||
Run crafted attack payloads against the plugin's own hooks to verify defenses.
|
||||
|
||||
## What was requested
|
||||
|
||||
The user ran `/security red-team` to test their hook defenses.
|
||||
|
||||
## Arguments
|
||||
|
||||
Parse `$ARGUMENTS` for:
|
||||
- `--category <name>` — filter: secrets, destructive, supply-chain, prompt-injection, pathguard, mcp-output, session-trifecta, hybrid, unicode-evasion, bash-evasion, hitl-traps, long-horizon, all
|
||||
- `--json` — raw JSON output
|
||||
- `--adaptive` — mutation-based evasion testing (5 mutation rounds per passing scenario)
|
||||
|
||||
Default: all categories, fixed mode.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Run the attack simulator:**
|
||||
|
||||
```
|
||||
node scanners/attack-simulator.mjs [--category <name>] [--verbose] [--adaptive]
|
||||
```
|
||||
|
||||
The simulator runs 64 attack scenarios across 12 categories against the plugin's hooks. Each scenario sends a crafted payload and verifies the hook blocks or detects it.
|
||||
|
||||
In **adaptive mode** (`--adaptive`), for each scenario that passes (attack blocked), the simulator applies 5 mutation rounds:
|
||||
1. Homoglyph substitution (Latin chars replaced with Cyrillic lookalikes)
|
||||
2. Encoding wrapping (URL-encoded keywords)
|
||||
3. Zero-width character injection (ZW chars inserted between keyword letters)
|
||||
4. Case alternation (aLtErNaTiNg case)
|
||||
5. Synonym substitution (keyword replacement from synonym table)
|
||||
|
||||
Bypasses are reported as findings but not auto-fixed.
|
||||
|
||||
2. **Present the results as a narrative report:**
|
||||
|
||||
For each category, explain:
|
||||
- What was tested (the attack type)
|
||||
- How many attacks were blocked
|
||||
- Whether defenses are adequate
|
||||
|
||||
If any scenarios fail, explain the gap and what hook needs attention.
|
||||
|
||||
In adaptive mode, also explain:
|
||||
- How many mutations were tested
|
||||
- Which mutations found bypasses
|
||||
- That bypasses are expected for synonym and encoding mutations (deterministic hooks cannot catch all evasions)
|
||||
|
||||
3. **Defense Score interpretation:**
|
||||
- **100%** — All hooks functioning correctly. No defense gaps.
|
||||
- **90-99%** — Minor gaps. Review failed scenarios.
|
||||
- **Below 90%** — Significant gaps. Hooks may be misconfigured or missing.
|
||||
|
||||
## Categories
|
||||
|
||||
| Category | Hook Tested | Scenarios |
|
||||
|----------|------------|-----------|
|
||||
| secrets | pre-edit-secrets.mjs | 7 secret types (AWS, GitHub, PEM, DB, Bearer, Azure, Slack) |
|
||||
| destructive | pre-bash-destructive.mjs | 8 commands (rm -rf, chmod 777, curl\|bash, fork bomb, mkfs, dd, eval) |
|
||||
| supply-chain | pre-install-supply-chain.mjs | 4 managers (npm, pip, cargo, gem) |
|
||||
| prompt-injection | pre-prompt-inject-scan.mjs | 6 patterns (override, spoofed headers, identity, evasion) |
|
||||
| pathguard | pre-write-pathguard.mjs | 6 paths (.env, .ssh, .aws, .npmrc, /etc, hooks) |
|
||||
| mcp-output | post-mcp-verify.mjs | 4 threats (injection, secrets, HTML traps, MCP injection) |
|
||||
| session-trifecta | post-session-guard.mjs | 3 patterns (classic trifecta, MCP-concentrated, volume) |
|
||||
| hybrid | post-mcp-verify.mjs | 8 patterns (P2SQL, recursive injection, XSS variants) |
|
||||
| unicode-evasion | pre-prompt-inject-scan.mjs | 6 patterns (Unicode Tags, ZW chars, homoglyphs, BIDI, HTML entities, multi-lang) |
|
||||
| bash-evasion | pre-bash-destructive.mjs | 5 patterns (empty quotes, dollar expansion, backslash splitting, supply chain) |
|
||||
| hitl-traps | post-mcp-verify.mjs | 4 patterns (approval urgency, summary suppression, scope minimization, cognitive load) |
|
||||
| long-horizon | post-session-guard.mjs | 3 patterns (delegation-after-input, sensitive path, MCP-concentrated trifecta) |
|
||||
|
||||
## Mutation Types (Adaptive Mode)
|
||||
|
||||
| Mutation | Technique | Expected Bypass Rate |
|
||||
|----------|-----------|---------------------|
|
||||
| homoglyph | Cyrillic/Latin lookalike substitution | Low (MEDIUM patterns detect) |
|
||||
| encoding | URL-encode keywords | High (hooks normalize some, not all) |
|
||||
| zero_width | Insert zero-width chars in keywords | Low (normalizer strips these) |
|
||||
| case_alternation | aLtErNaTiNg case | Low (regex uses /i flag) |
|
||||
| synonym | Replace with semantic equivalents | Medium (novel synonyms evade patterns) |
|
||||
|
||||
## Important
|
||||
|
||||
- This tests the plugin's OWN hooks — it does not perform real exploits
|
||||
- No network calls, no file modifications, no LLM invocations
|
||||
- Safe to run repeatedly — all state is cleaned up after each run
|
||||
- Adaptive mode bypasses are **expected** — they document evasion resistance limits
|
||||
121
plugins/llm-security/commands/registry.md
Normal file
121
plugins/llm-security/commands/registry.md
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
---
|
||||
name: security:registry
|
||||
description: Skill signature registry — view stats, scan and register skills, search known fingerprints
|
||||
allowed-tools: Bash, Read, Agent
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security registry [scan <path|url> | search <pattern>]
|
||||
|
||||
Local database of known skill fingerprints and risk profiles. Enables instant re-scan detection.
|
||||
|
||||
## Step 1: Parse Sub-command
|
||||
|
||||
Extract from `$ARGUMENTS`:
|
||||
- Empty or `stats` → **show stats**
|
||||
- `scan <path|url>` → **scan and register**
|
||||
- `search <pattern>` → **search registry**
|
||||
|
||||
Determine plugin root (parent of this `commands/` folder).
|
||||
|
||||
## Step 2a: Stats (default)
|
||||
|
||||
```bash
|
||||
node -e "
|
||||
import { getStats, listEntries } from '<plugin-root>/scanners/lib/skill-registry.mjs';
|
||||
const stats = getStats('<plugin-root>');
|
||||
const recent = listEntries({}, '<plugin-root>').slice(0, 5);
|
||||
console.log(JSON.stringify({ stats, recent }));
|
||||
" --input-type=module
|
||||
```
|
||||
|
||||
Display:
|
||||
|
||||
```
|
||||
## Skill Signature Registry
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total entries | X |
|
||||
| Scanned | X |
|
||||
| Seed | X |
|
||||
| ALLOW | X |
|
||||
| WARNING | X |
|
||||
| BLOCK | X |
|
||||
| Stale (>7d) | X |
|
||||
| Avg risk score | X/100 |
|
||||
|
||||
### Recent Entries
|
||||
| Name | Verdict | Risk | Last Scanned |
|
||||
```
|
||||
|
||||
## Step 2b: Scan and Register
|
||||
|
||||
Resolve target — if `$ARGUMENTS` contains a URL, clone via `node <plugin-root>/scanners/lib/git-clone.mjs clone "<url>"` first.
|
||||
|
||||
**Fingerprint:**
|
||||
|
||||
```bash
|
||||
node -e "
|
||||
import { fingerprintSkill, checkRegistry } from '<plugin-root>/scanners/lib/skill-registry.mjs';
|
||||
const result = fingerprintSkill('<target>');
|
||||
const check = checkRegistry(result.fingerprint, '<plugin-root>');
|
||||
console.log(JSON.stringify({ ...result, ...check }));
|
||||
" --input-type=module
|
||||
```
|
||||
|
||||
**If found and not stale:** Display cached result. Skip full scan.
|
||||
|
||||
```
|
||||
## Registry Hit
|
||||
|
||||
**Name:** <name> | **Fingerprint:** <first 12 chars>
|
||||
**Verdict:** <verdict> | **Risk Score:** <score>/100
|
||||
**Last scanned:** <date> | **Scan count:** <n>
|
||||
**Status:** Cached result (use `/security scan` to force re-scan)
|
||||
```
|
||||
|
||||
**If not found or stale:** Run `/security scan <target>`, then register:
|
||||
|
||||
```bash
|
||||
node -e "
|
||||
import { registerScan } from '<plugin-root>/scanners/lib/skill-registry.mjs';
|
||||
const result = registerScan({
|
||||
skillPath: '<target>',
|
||||
fingerprint: '<fingerprint>',
|
||||
name: '<name>',
|
||||
files: <files_json>,
|
||||
verdict: '<verdict>',
|
||||
risk_score: <score>,
|
||||
counts: <counts_json>,
|
||||
files_scanned: <n>
|
||||
}, '<plugin-root>');
|
||||
console.log(JSON.stringify(result.entry));
|
||||
" --input-type=module
|
||||
```
|
||||
|
||||
Display: "Registered: <name> (<fingerprint first 12>) — <verdict>"
|
||||
|
||||
Clean up clone if remote.
|
||||
|
||||
## Step 2c: Search
|
||||
|
||||
```bash
|
||||
node -e "
|
||||
import { searchRegistry } from '<plugin-root>/scanners/lib/skill-registry.mjs';
|
||||
const matches = searchRegistry('<pattern>', '<plugin-root>');
|
||||
console.log(JSON.stringify(matches));
|
||||
" --input-type=module
|
||||
```
|
||||
|
||||
Display results table:
|
||||
|
||||
```
|
||||
## Registry Search: "<pattern>"
|
||||
|
||||
**Matches:** X
|
||||
|
||||
| Name | Fingerprint | Verdict | Risk | Last Scanned |
|
||||
```
|
||||
|
||||
If no matches: "No entries matching '<pattern>'."
|
||||
147
plugins/llm-security/commands/scan.md
Normal file
147
plugins/llm-security/commands/scan.md
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
---
|
||||
name: security:scan
|
||||
description: Scan files, directories, or GitHub repos for security issues — secrets, injection vulnerabilities, supply chain risks, OWASP LLM patterns
|
||||
allowed-tools: Read, Glob, Grep, Bash, Agent
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security scan [path|url]
|
||||
|
||||
Scan target for security issues. Accepts local paths or GitHub URLs. Delegates to specialized agents sequentially.
|
||||
|
||||
## Step 1: Resolve Target
|
||||
|
||||
- If `$ARGUMENTS` contains `--deep` → strip it, set `run_deep_scan = true`
|
||||
- If `$ARGUMENTS` contains `--branch <name>` → strip it, set `branch = <name>`
|
||||
- If `$ARGUMENTS` is empty → `target = "."`, `clone_path = null`
|
||||
- If `$ARGUMENTS` starts with `https://github.com/` or `git@github.com:` →
|
||||
Run: `node <plugin-root>/scanners/lib/git-clone.mjs clone "<url>" [--branch <branch>]`
|
||||
If exit code != 0 → show error to user and **STOP**
|
||||
Set `clone_path` = stdout (trimmed), `target = clone_path`
|
||||
Set `remote_url = <url>` for display
|
||||
- Otherwise → `target = $ARGUMENTS`, `clone_path = null`
|
||||
|
||||
## Step 1.5: Pre-extraction (remote scans only)
|
||||
|
||||
If `clone_path != null` (target is a cloned remote repo):
|
||||
Get temp path: `node <plugin-root>/scanners/lib/fs-utils.mjs tmppath "content-extract.json"`
|
||||
Run: `node <plugin-root>/scanners/content-extractor.mjs "<target>" --output-file "<evidence_file>"`
|
||||
If exit code != 0 → warn user, set `evidence_file = null` (fall back to direct scan)
|
||||
Otherwise set `evidence_file` = the temp path. Print the compact summary line to user.
|
||||
|
||||
## Step 2: Detect Scan Type
|
||||
|
||||
**Single `.md` file:** `run_skill_scan = true`, `run_mcp_scan = false`
|
||||
|
||||
**Directory:** Glob for `**/commands/*.md`, `**/agents/*.md`, `**/skills/*/SKILL.md` → `run_skill_scan = true`. Glob for `**/.mcp.json`, `**/package.json`, `**/.claude/settings.json` with mcpServers → `run_mcp_scan = true`. Neither → skill scan only.
|
||||
|
||||
Record ISO 8601 timestamp.
|
||||
|
||||
## Step 3: Plugin Root
|
||||
|
||||
This file is at `<plugin-root>/commands/scan.md`. Use absolute paths for knowledge files.
|
||||
|
||||
## Step 3.5: Registry Check (local scans only)
|
||||
|
||||
If `clone_path == null` (local scan) and `run_skill_scan == true`:
|
||||
|
||||
```bash
|
||||
node -e "
|
||||
import { fingerprintSkill, checkRegistry } from '<plugin-root>/scanners/lib/skill-registry.mjs';
|
||||
const r = fingerprintSkill('<target>');
|
||||
const c = checkRegistry(r.fingerprint, '<plugin-root>');
|
||||
console.log(JSON.stringify({ fingerprint: r.fingerprint, name: r.name, files: r.files, ...c }));
|
||||
" --input-type=module
|
||||
```
|
||||
|
||||
If `found == true` and `stale == false`: display cached result and set `skip_skill_scan = true`:
|
||||
|
||||
```
|
||||
**Registry hit:** <name> (fingerprint: <first 12 chars>)
|
||||
Verdict: <verdict> | Risk: <score>/100 | Last scanned: <date> | Scans: <count>
|
||||
(Use `/security registry scan <target>` to force re-scan)
|
||||
```
|
||||
|
||||
Otherwise set `skip_skill_scan = false` and store `registry_fingerprint` and `registry_name` for post-scan registration.
|
||||
|
||||
## Step 4: Spawn Agents Sequentially
|
||||
|
||||
Use registered subagent types — they contain full scan procedures as system prompt.
|
||||
|
||||
**Skill Scanner** (if `run_skill_scan = true` AND `skip_skill_scan != true`): `subagent_type: "llm-security:skill-scanner-agent"`, `model: "sonnet"`:
|
||||
|
||||
If `evidence_file` is set (remote scan — evidence-package mode):
|
||||
> EVIDENCE-PACKAGE MODE. Read the pre-extracted evidence at: \<evidence_file\>
|
||||
> Read knowledge: \<plugin-root\>/knowledge/skill-threat-patterns.md, \<plugin-root\>/knowledge/secrets-patterns.md
|
||||
> Analyze the JSON sections: injection_findings, frontmatter_inventory, shell_commands, credential_references, persistence_signals, claude_md_analysis, cross_instruction_flags.
|
||||
> DO NOT use Read/Glob/Grep on the target directory — all evidence is in the package.
|
||||
> `[INJECTION-PATTERN-STRIPPED]` markers are confirmed findings — report them.
|
||||
> Return findings with severity, category, file, line, OWASP ref, evidence, remediation.
|
||||
> End with JSON: `{"scanner":"skill-scanner","verdict":"ALLOW|WARNING|BLOCK","risk_score":N,"counts":{"critical":0,"high":0,"medium":0,"low":0,"info":0},"files_scanned":N}`
|
||||
|
||||
Otherwise (local scan — direct mode):
|
||||
> Scan target: \<target\>
|
||||
> Read: \<plugin-root\>/knowledge/skill-threat-patterns.md, \<plugin-root\>/knowledge/secrets-patterns.md
|
||||
> Return findings with severity, category, file, line, OWASP ref, evidence, remediation.
|
||||
> End with JSON: `{"scanner":"skill-scanner","verdict":"ALLOW|WARNING|BLOCK","risk_score":N,"counts":{"critical":0,"high":0,"medium":0,"low":0,"info":0},"files_scanned":N}`
|
||||
|
||||
**MCP Scanner** (if `run_mcp_scan = true`, run AFTER skill scanner): `subagent_type: "llm-security:mcp-scanner-agent"`, `model: "sonnet"`:
|
||||
|
||||
If `evidence_file` is set (remote scan — evidence-package mode):
|
||||
> EVIDENCE-PACKAGE MODE. Read the pre-extracted evidence at: \<evidence_file\>
|
||||
> Read: \<plugin-root\>/knowledge/mcp-threat-patterns.md
|
||||
> Analyze: mcp_tool_descriptions (check hidden instructions, length >500, injection_detected), shell_commands, credential_references.
|
||||
> DO NOT use Read/Glob/Grep on the target directory.
|
||||
> Return findings with severity, category, evidence, remediation.
|
||||
> End with JSON: `{"scanner":"mcp-scanner","verdict":"ALLOW|WARNING|BLOCK","risk_score":N,"counts":{"critical":0,"high":0,"medium":0,"low":0,"info":0},"files_scanned":N}`
|
||||
|
||||
Otherwise (local scan — direct mode):
|
||||
> Scan target: \<target\>
|
||||
> Read: \<plugin-root\>/knowledge/mcp-threat-patterns.md
|
||||
> Return findings with severity, category, server name, evidence, remediation.
|
||||
> End with JSON: `{"scanner":"mcp-scanner","verdict":"ALLOW|WARNING|BLOCK","risk_score":N,"counts":{"critical":0,"high":0,"medium":0,"low":0,"info":0},"files_scanned":N}`
|
||||
|
||||
## Step 5: Aggregate and Report
|
||||
|
||||
Combine counts. `risk_score = min(100, critical*25 + high*10 + medium*4 + low*1)`.
|
||||
Verdict: critical≥1 OR score≥61 → BLOCK, high≥1 OR score≥21 → WARNING, else ALLOW.
|
||||
|
||||
Output banner then all findings grouped by severity (critical→info). Each finding:
|
||||
`### [SEV] Title` with Category, File:line, OWASP, Evidence, Remediation.
|
||||
|
||||
For TFA (Toxic Flow Analysis) findings, render the chain description prominently:
|
||||
- Show the 3 trifecta legs (Input, Access, Exfil) with their evidence
|
||||
- Note mitigation status (which hooks are active)
|
||||
- Group direct trifectas separately from cross-component trifectas
|
||||
|
||||
## Step 5.5: Register in Skill Registry (local scans only)
|
||||
|
||||
If `clone_path == null` and `skip_skill_scan != true` and `registry_fingerprint` is set:
|
||||
|
||||
```bash
|
||||
node -e "
|
||||
import { registerScan } from '<plugin-root>/scanners/lib/skill-registry.mjs';
|
||||
registerScan({
|
||||
skillPath: '<target>',
|
||||
fingerprint: '<registry_fingerprint>',
|
||||
name: '<registry_name>',
|
||||
files: <registry_files_json>,
|
||||
verdict: '<computed_verdict>',
|
||||
risk_score: <computed_risk_score>,
|
||||
counts: <computed_counts_json>,
|
||||
files_scanned: <files_scanned>
|
||||
}, '<plugin-root>');
|
||||
" --input-type=module
|
||||
```
|
||||
|
||||
## Step 6: Deep Scan (only if `--deep`)
|
||||
|
||||
If `run_deep_scan = true`, run `/security deep-scan <target>` logic:
|
||||
Get temp path, run `node <plugin-root>/scanners/scan-orchestrator.mjs "<target>" --output-file "<tmp>"`.
|
||||
Parse stdout aggregate JSON. Merge with LLM findings. Re-evaluate verdict. Output "Deep Scan Findings" section with CRITICAL/HIGH only.
|
||||
|
||||
## Step 7: Cleanup (only if remote)
|
||||
|
||||
If `clone_path != null`:
|
||||
Run: `node <plugin-root>/scanners/lib/git-clone.mjs cleanup "<clone_path>"`
|
||||
If cleanup fails → warn: "Could not remove temp dir <clone_path> — remove manually."
|
||||
74
plugins/llm-security/commands/security.md
Normal file
74
plugins/llm-security/commands/security.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
name: security
|
||||
description: LLM Security — security scanning, auditing, and threat modeling for Claude Code projects
|
||||
allowed-tools: Read, Glob
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# LLM Security Plugin
|
||||
|
||||
Security scanning, auditing, and threat modeling for Claude Code projects.
|
||||
Based on OWASP LLM Top 10 (2025) and OWASP Agentic AI Top 10.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Description | When to use |
|
||||
|---------|-------------|-------------|
|
||||
| `/security scan [path\|url]` | Scan skills, MCP servers, directories, or GitHub repos | Before installing a new skill or MCP server |
|
||||
| `/security scan [path\|url] --deep` | Enhanced scan: LLM agents + 7 deterministic scanners | Deep analysis with entropy, taint, git forensics |
|
||||
| `/security deep-scan [path]` | Run 7 deterministic scanners only (no LLM agents) | Fast, reproducible, deterministic-only analysis |
|
||||
| `/security audit` | Full project security audit with A-F grading | Periodic review (monthly recommended) |
|
||||
| `/security plugin-audit [path\|url]` | Dedicated plugin security audit with trust verdict | Before installing a third-party plugin |
|
||||
| `/security mcp-audit [--live]` | Focused audit of all installed MCP servers | After adding MCP servers or on suspicion |
|
||||
| `/security mcp-inspect` | Live inspection — connect to MCP servers, scan tool descriptions | Verify running servers have safe tool descriptions |
|
||||
| `/security posture` | Quick security posture scorecard | Daily/weekly health check |
|
||||
| `/security threat-model` | Interactive STRIDE/MAESTRO threat modeling session | When designing new architecture |
|
||||
| `/security diff [path]` | Compare scan against stored baseline — shows new/resolved/moved | Track security changes over time |
|
||||
| `/security watch [path] [--interval 6h]` | Monitor path continuously — runs diff on interval | Ongoing security monitoring |
|
||||
| `/security clean [path]` | Clean/remediate security findings — auto-fixes, confirms semi-auto, reports manual | Sanitizing third-party plugin before install |
|
||||
| `/security supply-check [path]` | Re-audit installed deps — lockfiles vs blocklists, OSV.dev CVEs, typosquats | Periodic dependency audit |
|
||||
| `/security dashboard` | Cross-project security dashboard — machine-wide posture overview | Machine-wide security health check |
|
||||
| `/security harden [path]` | Generate Grade A security config — settings.json, CLAUDE.md, .gitignore | Hardening a new or existing project |
|
||||
| `/security red-team [--category]` | Attack simulation — test hook defenses with crafted payloads | Verify hooks actually block what they claim |
|
||||
| `/security pre-deploy` | Pre-deployment security checklist | Before pushing to production |
|
||||
|
||||
## Quick Start
|
||||
|
||||
- **New to security?** Start with `/security posture` for a quick health check
|
||||
- **Evaluating a plugin?** Run `/security plugin-audit path/to/plugin` for a full trust assessment
|
||||
- **Inspecting live MCP servers?** Run `/security mcp-inspect` to connect and scan tool descriptions
|
||||
- **Evaluating a remote plugin?** Run `/security plugin-audit https://github.com/user/repo`
|
||||
- **Scanning a remote repo?** Run `/security scan https://github.com/user/repo`
|
||||
- **Scanning individual files?** Run `/security scan path/to/file` for targeted analysis
|
||||
- **Want deterministic analysis?** Run `/security deep-scan .` for 7 automated scanners (entropy, unicode, taint, git, deps, permissions, network)
|
||||
- **Tracking changes?** Run `/security diff .` to compare against a stored baseline
|
||||
- **Continuous monitoring?** Run `/security watch .` for interval-based security diffs (default 6h)
|
||||
- **Full analysis?** Run `/security scan . --deep` to combine LLM + deterministic scanners
|
||||
- **Sanitizing a plugin?** `/security clean path/to/plugin` — auto-fix + confirm + report
|
||||
- **Hardening a project?** Run `/security harden .` to generate Grade A configuration
|
||||
- **Machine-wide overview?** Run `/security dashboard` for a cross-project security dashboard
|
||||
- **Testing your defenses?** Run `/security red-team` to simulate 38 attacks against your hooks
|
||||
- **Heading to production?** Run `/security pre-deploy` for the checklist
|
||||
- **Need deep analysis?** Run `/security threat-model` for guided threat modeling
|
||||
|
||||
## What's Protected (Hooks)
|
||||
|
||||
This plugin includes automated security hooks that run on every operation:
|
||||
|
||||
| Hook | Protects Against |
|
||||
|------|-----------------|
|
||||
| Secret detection | API keys, tokens, passwords in code |
|
||||
| Path guarding | Writes to .env, .ssh, credentials files |
|
||||
| Destructive command blocking | rm -rf, force push, pipe-to-shell |
|
||||
| MCP output verification | Data leakage in MCP tool outputs |
|
||||
|
||||
These hooks are always active when the plugin is installed — no commands needed.
|
||||
|
||||
## Knowledge Base
|
||||
|
||||
Built on research-backed threat intelligence:
|
||||
- OWASP LLM Top 10 (2025) — 10 LLM-specific risk categories
|
||||
- OWASP Agentic AI Top 10 — Agent-specific threats (ASI01-ASI10)
|
||||
- ToxicSkills study — Real-world malicious skill patterns
|
||||
- MCPTox research — MCP server vulnerability patterns
|
||||
- Mitigation matrix — Threat-to-control mapping for Claude Code
|
||||
47
plugins/llm-security/commands/supply-check.md
Normal file
47
plugins/llm-security/commands/supply-check.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
name: security:supply-check
|
||||
description: Re-audit installed dependencies — check lockfiles against blocklists, OSV.dev CVEs, and typosquat detection
|
||||
allowed-tools: Read, Bash
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security supply-check [path]
|
||||
|
||||
Re-audit installed dependencies in lockfiles (package-lock.json, yarn.lock, requirements.txt, Pipfile.lock) against blocklists, OSV.dev CVE database, and typosquat detection.
|
||||
|
||||
Unlike `deep-scan` (which includes dep-auditor among 9 scanners), this command runs ONLY the supply-chain-recheck scanner for a focused dependency audit.
|
||||
|
||||
## Step 1: Setup
|
||||
|
||||
- `$ARGUMENTS` empty → target = cwd. Otherwise target = first argument.
|
||||
- Plugin root = parent of this `commands/` folder.
|
||||
|
||||
## Step 2: Run Scanner
|
||||
|
||||
```bash
|
||||
node <plugin-root>/scanners/supply-chain-recheck-cli.mjs "<target>"
|
||||
```
|
||||
|
||||
**Important:** This scanner calls OSV.dev API. If offline, blocklist and typosquat checks still run but CVE detection is skipped (an INFO finding notes this).
|
||||
|
||||
The scanner outputs JSON to stdout. Parse it.
|
||||
|
||||
## Step 3: Present Results
|
||||
|
||||
Show a summary banner:
|
||||
|
||||
```
|
||||
## Supply Chain Re-check: [target]
|
||||
Status: [ok|skipped|error] | Findings: XC XH XM XL XI | Files: N lockfile(s)
|
||||
```
|
||||
|
||||
If `osv_offline: true` in result, note: "OSV.dev was unreachable — CVE check was skipped. Blocklist and typosquat checks completed."
|
||||
|
||||
## Step 4: Detail Findings
|
||||
|
||||
For each finding, show:
|
||||
- Severity badge and title
|
||||
- File (lockfile) and evidence
|
||||
- Recommendation
|
||||
|
||||
Group by severity (CRITICAL first). If zero findings: "No supply chain issues detected in N lockfile(s)."
|
||||
27
plugins/llm-security/commands/threat-model.md
Normal file
27
plugins/llm-security/commands/threat-model.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
name: security:threat-model
|
||||
description: Interactive threat modeling using STRIDE and MAESTRO frameworks — guides architecture analysis and generates threat model document
|
||||
allowed-tools: Read, Glob, Grep, AskUserQuestion, Agent
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security threat-model
|
||||
|
||||
Interactive threat modeling — STRIDE x MAESTRO, 5-phase interview, complete threat model document.
|
||||
|
||||
## Run Session
|
||||
|
||||
Spawn `subagent_type: "llm-security:threat-modeler-agent"`, `model: "opus"`:
|
||||
|
||||
> Run the full 5-phase interactive threat modeling session.
|
||||
> Read these knowledge files (absolute paths):
|
||||
> - \<plugin-root\>/knowledge/skill-threat-patterns.md
|
||||
> - \<plugin-root\>/knowledge/mcp-threat-patterns.md
|
||||
> Follow your interview workflow: Architecture Discovery → Component Mapping → Threat Identification (STRIDE x MAESTRO) → Risk Assessment → Mitigation Mapping.
|
||||
> Output the complete threat model document directly to the conversation.
|
||||
|
||||
## After Session
|
||||
|
||||
- To save: ask user if they want it written to `threat-model.md`
|
||||
- To verify mitigations: `/security posture`
|
||||
- For production readiness: `/security pre-deploy`
|
||||
58
plugins/llm-security/commands/watch.md
Normal file
58
plugins/llm-security/commands/watch.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
name: security:watch
|
||||
description: Continuous security monitoring — runs diff on a recurring interval
|
||||
allowed-tools: Bash, Read, Skill
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# /security watch [path] [--interval 6h]
|
||||
|
||||
Set up continuous security monitoring. Establishes a baseline, then runs `/security diff` on a recurring interval to detect regressions.
|
||||
|
||||
## Step 1: Parse Arguments
|
||||
|
||||
Extract from `$ARGUMENTS`:
|
||||
- **path** — first non-flag argument (default `.`)
|
||||
- **--interval \<value\>** — loop interval like `6h`, `30m`, `1h` (default `6h`)
|
||||
|
||||
## Step 2: Establish Baseline
|
||||
|
||||
Determine plugin root (parent of this `commands/` folder) and resolve the target path.
|
||||
|
||||
```bash
|
||||
node <plugin-root>/scanners/scan-orchestrator.mjs "<target>" --save-baseline
|
||||
```
|
||||
|
||||
Parse stdout JSON. Display:
|
||||
|
||||
```
|
||||
## Security Watch: <target>
|
||||
|
||||
**Baseline established** at <timestamp>
|
||||
**Findings:** XC XH XM XL XI | **Risk Score:** X/100 | **Verdict:** ALLOW/WARNING/BLOCK
|
||||
|
||||
Starting watch with interval: <interval>
|
||||
```
|
||||
|
||||
If the verdict is BLOCK, add a warning: "Initial scan shows BLOCK verdict — you will be alerted to any new findings above this baseline."
|
||||
|
||||
## Step 3: Start Loop
|
||||
|
||||
Use the **Skill** tool to invoke the built-in `/loop` skill:
|
||||
- skill: `loop`
|
||||
- args: `<interval> /security diff <target>`
|
||||
|
||||
This runs `/security diff <target>` every `<interval>`. Each diff compares against the latest baseline and saves a new one — a rolling window of changes.
|
||||
|
||||
## Step 4: Advisory
|
||||
|
||||
After starting the loop, display:
|
||||
|
||||
```
|
||||
**Watch active.** `/security diff <target>` runs every <interval>.
|
||||
|
||||
To run as a system cron job instead:
|
||||
node <plugin-root>/scanners/watch-cron.mjs
|
||||
|
||||
To stop watching: Escape or Ctrl+C
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue