- name
- atv-security
- description
- Unified ATV security audit. Scans agentic config (.github/, .vscode/) using AgentShield's 33-rule taxonomy AND application source code for OWASP Top 10 + STRIDE threats. Triggers on 'security scan', 'audit security', 'check config security', 'atv-security', 'security audit', 'scan for vulnerabilities', 'cso', 'owasp scan', 'threat model', 'stride analysis', 'application security', 'security review code'.
- argument-hint
- [mode: report (default) | fix] [scope: full (default) | config | owasp | stride | <path>]
# /atv-security — Unified Security Auditor
Scan your project for security issues across two surfaces:
1. **Agentic configuration** — `.github/`, `.vscode/` configs (33 rules adapted from [AgentShield](https://github.com/affaan-m/agentshield)).
2. **Application source code** — OWASP Top 10 (2021) static checks + STRIDE threat model.
> **Heritage:** This skill absorbs the former `/cso` skill. Old `/cso` triggers still route here. The on-disk security report file keeps the legacy `<!-- cso -->` marker block so existing reports stay structurally compatible.
**5 config categories:** Secrets · Permissions · Hooks · MCP Servers · Agents & Skills
## Arguments
<args> #$ARGUMENTS </args>
**Argument grammar:** Two independent axes, parsed in order.
1. **Mode** — if any token in `$ARGUMENTS` matches `fix` (case-insensitive), mode = `fix`. Otherwise mode = `report` (default).
2. **Scope** — examine the remaining tokens (after stripping `fix`):
- Token `config` → scope = `config` (config audit only; skip OWASP/STRIDE)
- Token `owasp` → scope = `owasp` (OWASP scan only; skip config + STRIDE)
- Token `stride` → scope = `stride` (STRIDE only; skip config + OWASP)
- Token that looks like a file/directory path (contains `/` or `\` or matches an existing path) → scope = `<path>` (run OWASP/STRIDE narrowed to that path; skip config)
- No remaining tokens, or token is `full` → scope = `full` (default; run everything available)
**Examples:**
- `/atv-security` → `mode=report scope=full`
- `/atv-security fix` → `mode=fix scope=full`
- `/atv-security config fix` or `/atv-security fix config` → `mode=fix scope=config`
- `/atv-security owasp` → `mode=report scope=owasp`
- `/atv-security src/api/` → `mode=report scope=src/api/`
## Execution Flow
```
Phase 1: Discovery → Detect config surfaces + app source stack
Phase 2: Tier 1 Config → Deterministic regex scan of .github/, .vscode/ (skip if scope ∉ {full, config})
Phase 3: Tier 2 Config → LLM-assessed config rules (skip if scope ∉ {full, config})
Phase 4: OWASP Top 10 → Application source code scan (skip if no source OR scope ∉ {full, owasp, <path>})
Phase 5: STRIDE → Threat model the application (skip if no source OR scope ∉ {full, stride, <path>})
Phase 6: Score & Grade → Per-surface grades with N/A semantics
Phase 7: Output → Combined report (config + OWASP + STRIDE)
Phase 8: Persist → Upsert into docs/security/YYYY-MM-DD-security-report.md (both marker blocks)
Phase 9: Fix → Opt-in safe fixes for auto-fixable config rules (only when mode=fix)
```
---
## Phase 1: Discovery
Use `file_search` and `list_dir` to detect both surfaces in parallel.
### 1a. ATV configuration surfaces
| Surface | File Pattern | Category |
|---------|-------------|----------|
| Instructions | `.github/copilot-instructions.md` | Agents & Skills |
| MCP Config | `.github/copilot-mcp-config.json` | MCP Servers |
| Skills | `.github/skills/**/*.md` | Agents & Skills |
| Agents | `.github/agents/**/*.agent.md` | Agents & Skills |
| Hooks | `.github/hooks/copilot-hooks.json` + `.github/hooks/scripts/**` | Hooks |
| Setup Steps | `.github/copilot-setup-steps.yml` | Hooks |
| VS Code | `.vscode/settings.json`, `.vscode/extensions.json` | Permissions |
Set `hasConfig = true` if any of the above are found.
### 1b. Application source stack
| Signal | Stack | Key files to scan |
|--------|-------|-------------------|
| `package.json`, `*.ts`, `*.js` | Node.js / TypeScript | `src/**`, `routes/**`, `api/**`, `pages/**` |
| `requirements.txt`, `*.py` | Python | `app/**`, `src/**`, `views/**`, `api/**` |
| `Gemfile`, `*.rb` | Ruby / Rails | `app/**`, `config/**`, `db/**` |
| `go.mod`, `*.go` | Go | `**/*.go` |
| `*.cs`, `*.csproj` | .NET | `**/*.cs`, `Controllers/**` |
| `pom.xml`, `*.java` | Java | `src/**/*.java` |
Set `hasSource = true` if any application source files are found. If scope is a path, narrow source detection to that path.
Record: list of discovered config files, detected stack, total source files found, entry points identified.
### 1c. Bail rule
If `!hasConfig && !hasSource`: report "No ATV configuration or application source detected. Run `npx atv-starterkit init` to scaffold an agentic environment, or run `/atv-security` from a project directory." and stop.
If `scope=config` and `!hasConfig`: report "Scope `config` requested but no `.github/` directory found." and stop.
If `scope ∈ {owasp, stride, <path>}` and `!hasSource`: report "Scope requires application source, but none found." and stop.
---
## Phase 2: Tier 1 Config Scan — Deterministic Detection
> Run only when `hasConfig && scope ∈ {full, config}`.
Run `grep_search` with `isRegexp: true` for each pattern below. For each match, record a finding with the specified fields.
### Secrets Rules
| Rule | Pattern | Scope | Severity | Fix |
|------|---------|-------|----------|-----|
| SEC-01 | `sk-ant-[a-zA-Z0-9]{20,}` | All `.github/**`, `.vscode/**` | 🔴 critical | Replace with `${ANTHROPIC_API_KEY}` env var reference |
| SEC-02 | `sk-proj-[a-zA-Z0-9]{20,}` | All `.github/**`, `.vscode/**` | 🔴 critical | Replace with `${OPENAI_API_KEY}` env var reference |
| SEC-03 | `AKIA[0-9A-Z]{16}` | All `.github/**`, `.vscode/**` | 🔴 critical | Replace with `${AWS_ACCESS_KEY_ID}` env var reference |
For rules whose regex patterns require alternation, use the entries below instead of markdown table rows so the raw `|` characters remain valid for `isRegexp: true`:
- **SEC-04**
- **Pattern:** `(?:ghp_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22,})`
- **Scope:** All `.github/**`, `.vscode/**`
- **Severity:** 🔴 critical
- **Fix:** Replace with `${GITHUB_TOKEN}` env var reference
- **SEC-05**
- **Pattern:** `(?:Bearer [a-zA-Z0-9_\-\.]{20,}|mongodb(\+srv)?://[^\s]+|postgres(ql)?://[^\s]+|mysql://[^\s]+|redis://[^\s]+)`
- **Scope:** All `.github/**`, `.vscode/**`
- **Severity:** 🟡 high
- **Fix:** Replace with `${ENV_VAR}` reference appropriate to the service
### MCP Server Rules (grep-detectable)
| Rule | Pattern | Scope | Severity | Fix |
|------|---------|-------|----------|-----|
| MCP-02 | `"tools"\s*:\s*\["?\*"?\]` | `.github/copilot-mcp-config.json` | 🟡 high | Scope to specific tools needed: `["tool1", "tool2"]` |
| MCP-03 | `autoApprove` | `.github/copilot-mcp-config.json` | 🟢 medium | Remove autoApprove or restrict to safe read-only tools |
- **MCP-04**
- **Pattern:** `(?:sk-ant-|sk-proj-|AKIA|ghp_|Bearer )`
- **Scope:** `.github/copilot-mcp-config.json` env sections
- **Severity:** 🔴 critical
- **Fix:** Use `${input:VAR}` or `${ENV_VAR}` references
### Hook Rules (grep-detectable)
- **HOOK-01**
- **Pattern:** `(?:curl.*\$\{|wget.*\$\{|eval.*\$\{)`
- **Scope:** `.github/hooks/scripts/**`
- **Severity:** 🟡 high
- **Fix:** Validate/sanitize variables before use in network/eval commands
- **HOOK-02**
- **Pattern:** `(?:curl\s+-X\s+POST.*\$|wget\s+--post)`
- **Scope:** `.github/hooks/scripts/**`
- **Severity:** 🔴 critical
- **Fix:** Remove data exfiltration patterns or restrict to known-safe URLs
| Rule | Pattern | Scope | Severity | Fix |
|------|---------|-------|----------|-----|
| HOOK-03a | `2>/dev/null` | `.github/hooks/scripts/**` | 🟢 medium | Log errors instead of suppressing them silently |
| HOOK-03b | `\|\| true$` | `.github/hooks/scripts/**` | 🟢 medium | Log errors instead of suppressing them silently |
| HOOK-03c | `\|\| exit 0$` | `.github/hooks/scripts/**` | 🟢 medium | Log errors instead of suppressing them silently |
### Agent & Skill Rules (grep-detectable)
| Rule | Pattern | Scope | Severity | Fix |
|------|---------|-------|----------|-----|
| AGENT-01 | `[\u200B\u200C\u200D\uFEFF]` | `.github/skills/**`, `.github/agents/**`, `.github/copilot-instructions.md` | 🔴 critical | Remove zero-width characters — likely hidden instruction injection |
| AGENT-02 | `[A-Za-z0-9+/]{80,}={0,2}` | `.github/skills/**`, `.github/agents/**` | 🟢 medium | Decode and inspect — may contain hidden instructions. Ignore if preceded by `sha256:`, `data:`, or `http` |
### Permission Rules (grep-detectable)
| Rule | Pattern | Scope | Severity | Fix |
|------|---------|-------|----------|-----|
| PERM-01 | `security\.workspace\.trust\.enabled"?\s*:\s*false\|chat\.tools\.autoApprove"?\s*:\s*true` | `.vscode/settings.json` | 🟢 medium | Enable workspace trust; disable agent-tool auto-approval |
**Execution:** For each rule, run `grep_search` with the pattern and `includePattern` matching the scope. Record every match as a finding with: rule ID, category, severity, title, file path, matched evidence (truncated to 100 chars), and fix suggestion.
---
View on GitHub