# Vuln Scan

> Autonomous vulnerability scanning pipeline — scans repos for security issues and produces markdown + SARIF reports. Invoke via /vuln-scan [path].

- **Type:** Skill
- **Install:** `agentstack add skill-thapr0digy-skills-vuln-scan`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [thapr0digy](https://agentstack.voostack.com/s/thapr0digy)
- **Installs:** 0
- **Category:** [Content & Media](https://agentstack.voostack.com/c/content-and-media)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [thapr0digy](https://github.com/thapr0digy)
- **Source:** https://github.com/thapr0digy/skills/tree/main/plugins/vuln-scan/skills/vuln-scan

## Install

```sh
agentstack add skill-thapr0digy-skills-vuln-scan
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# vuln-scan — Coordinator

You are the orchestrator of a 7-phase autonomous vulnerability scanning pipeline. When a user invokes `/vuln-scan [path]`, follow every step below exactly. Make no decisions interactively — every choice is defined here. Do not prompt the user at any point during execution.

---

## Step 1 — Parse Arguments

Extract the target path from the skill invocation arguments.

- If an argument was provided, use it as the target path (resolve to an absolute path if relative).
- If no argument was provided, default to the current working directory.

Store this value as `TARGET_PATH` for all subsequent steps.

### Derive OUTPUT_DIR

Compute the output directory by deriving a sanitized directory name from `TARGET_PATH` relative to the current working directory:

1. Compute the relative path of `TARGET_PATH` from the current working directory. If `TARGET_PATH` is the current working directory, use the directory's basename.
2. Replace path separators (`/`) with hyphens (`-`). Remove leading/trailing hyphens.
3. Set `OUTPUT_DIR` to `{CWD}/vuln-scan-results/{sanitized-name}` where `{CWD}` is the current working directory.

**Examples:**
- `/vuln-scan` (target = CWD `/home/user/myapp`) → `OUTPUT_DIR` = `/home/user/myapp/vuln-scan-results/myapp`
- `/vuln-scan src/api` → `OUTPUT_DIR` = `/home/user/myapp/vuln-scan-results/src-api`
- `/vuln-scan /other/repo` → `OUTPUT_DIR` = `/home/user/myapp/vuln-scan-results/other-repo`

This ensures each scan target gets its own results directory that persists across runs.

---

## Step 2 — Validate Target

Use the Bash tool to confirm the target is a usable directory:

```bash
[ -d "{TARGET_PATH}" ] && echo "exists" || echo "missing"
```

Then use Glob to check that the directory contains at least one source file (any file matching `**/*.*` excluding `vuln-scan-results/**`).

**If the directory does not exist or contains no source files:** output an error message to the user explaining the problem and stop. Do not proceed.

---

## Step 3 — Setup Output Directory

Check whether `{OUTPUT_DIR}/config.json` exists (this file is user-created, NOT generated). If it exists, preserve it across the cleanup.

Execute the following using the Bash tool. Run these as a single shell script block.

```bash
# Preserve user config if it exists (stash in parent vuln-scan-results/ dir)
[ -f "{OUTPUT_DIR}/config.json" ] && mv "{OUTPUT_DIR}/config.json" "{OUTPUT_DIR}/../.vuln-scan-config-preserve.json"

# Remove previous scan output
rm -rf "{OUTPUT_DIR}"

# Create fresh output directories
mkdir -p "{OUTPUT_DIR}/findings"

# Restore user config if it was preserved
[ -f "{OUTPUT_DIR}/../.vuln-scan-config-preserve.json" ] && mv "{OUTPUT_DIR}/../.vuln-scan-config-preserve.json" "{OUTPUT_DIR}/config.json"
```

Initialize the scan log by writing the following JSON line to `{OUTPUT_DIR}/scan.log` using the Write tool:

```json
{"ts": "", "phase": "coordinator", "event": "start", "target": "{TARGET_PATH}"}
```

---

## Step 4 — Phase 1: Recon

**Goal:** Produce `{OUTPUT_DIR}/repo-profile.json`.

1. Use the Read tool to read the file at `{SKILL_DIR}/phases/recon.md` where `{SKILL_DIR}` is the directory containing this SKILL.md file (i.e., the `skills/vuln-scan/` directory within the repository where you were loaded from).
2. In the loaded text, replace every occurrence of `{{TARGET_PATH}}` with the actual value of `TARGET_PATH`, and every occurrence of `{{OUTPUT_DIR}}` with the actual value of `OUTPUT_DIR`.
3. Use the Agent tool to dispatch the prepared prompt as a subagent. Use this description: `"Run Phase 1 recon"`.
4. Wait for the subagent to return.
5. Append this line to `{OUTPUT_DIR}/scan.log`:
   - On success: `{"ts": "", "phase": "recon", "event": "completed", "duration_s": }`
   - On failure: `{"ts": "", "phase": "recon", "event": "failed", "reason": ""}`
6. Use the Read tool to load `{OUTPUT_DIR}/repo-profile.json`.
   - **If this file does not exist or is not valid JSON:** write a `failed` log entry, output a single error message to the user ("Phase 1 (Recon) failed — cannot continue without a repo profile"), and stop. Do not proceed to any further phase.
7. Store the file contents as `REPO_PROFILE`.

---

## Step 5 — Phase 2: Threat Model

**Goal:** Produce `{OUTPUT_DIR}/threat-model.json`.

1. Use the Read tool to read `{SKILL_DIR}/phases/threat-model.md`.
2. Replace every occurrence of `{{REPO_PROFILE}}` with the contents of `REPO_PROFILE`.
3. Replace `{{OUTPUT_DIR}}` with the actual value of `OUTPUT_DIR`.
4. Replace `{{SERVICES}}` with the `services` array from `REPO_PROFILE` (extracted as a JSON array string). If `is_monorepo` is `false` in the repo profile, replace `{{SERVICES}}` with `[]`.
5. Dispatch the prepared prompt as an Agent subagent. Description: `"Run Phase 2 threat model"`.
6. Wait for the subagent to return.
7. Use the Read tool to load `{OUTPUT_DIR}/threat-model.json`.
   - **If the file exists and is valid JSON:** store its contents as `THREAT_MODEL`. Append a `completed` log entry.
   - **If the file is missing or invalid:** store `THREAT_MODEL` as the string `{}`. Append a `failed` log entry with `"reason": "threat model output missing, continuing with empty model"`. Do not abort — partial results are acceptable.

---

## Step 6 — Phases 3–5: Parallel Scanning

**Goal:** Run static analysis, code review, and dependency scan simultaneously.

### 6a — Prepare all three prompts

Use the Read tool three times (may be parallelized) to load:
- `{SKILL_DIR}/phases/static-analysis.md`
- `{SKILL_DIR}/phases/code-review.md`
- `{SKILL_DIR}/phases/dependency-scan.md`

For each loaded text, perform the following replacements (skip a replacement if that placeholder does not appear in the file):
- Replace `{{REPO_PROFILE}}` with the contents of `REPO_PROFILE`.
- Replace `{{THREAT_MODEL}}` with the contents of `THREAT_MODEL`.
- Replace `{{OUTPUT_DIR}}` with the actual value of `OUTPUT_DIR`.
- Replace `{{SERVICES}}` with the `services` array from `REPO_PROFILE` (extracted as a JSON array string). If `is_monorepo` is `false` in the repo profile, replace `{{SERVICES}}` with `[]`.

### 6b — Dispatch all three agents in a single message

**CRITICAL:** You MUST invoke all three Agent tool calls in a single response message. This triggers parallel execution. Do not send them in separate messages.

Use these descriptions:
- Static analysis agent: `"Run Phase 3 static analysis"`
- Code review agent: `"Run Phase 4 code review"`
- Dependency scan agent: `"Run Phase 5 dependency scan"`

### 6c — Handle results

After all three subagents return, append a log entry for each:
- `{"ts": "", "phase": "", "event": "completed", "duration_s": }`
- `{"ts": "", "phase": "", "event": "failed", "reason": ""}`

If the parallel dispatch itself fails (e.g., tool error before any agent runs), fall back to dispatching each of the three agents sequentially, one at a time, with separate Agent tool calls. Log a `skipped` entry for parallel mode:

```json
{"ts": "", "phase": "parallel-dispatch", "event": "skipped", "reason": "parallel dispatch failed, falling back to sequential"}
```

Do not abort if one or more of these phases fail — proceed to validation with whatever findings were produced.

---

## Step 7 — Phase 6: Validation

**Goal:** Produce `{OUTPUT_DIR}/validated-findings.json`.

1. Use the Read tool to read `{SKILL_DIR}/phases/validation.md`.

2. Perform these replacements:
   - Replace `{{THREAT_MODEL}}` with the contents of `THREAT_MODEL`.
   - Replace `{{OUTPUT_DIR}}` with the actual value of `OUTPUT_DIR`.
   - Replace `{{FINDINGS_DIR}}` with the path `{OUTPUT_DIR}/findings`.
   - Replace `{{SERVICES}}` with the `services` array from `REPO_PROFILE` (extracted as a JSON array string). If `is_monorepo` is `false` in the repo profile, replace `{{SERVICES}}` with `[]`.

3. For each findings file, attempt to read it with the Read tool. If the file exists, replace the corresponding placeholder with its contents. If the file does not exist, leave the placeholder as-is (the validation phase prompt handles absent data gracefully).

   | Placeholder                    | File path                                              |
   |-------------------------------|--------------------------------------------------------|
   | `{{STATIC_ANALYSIS_FINDINGS}}` | `{OUTPUT_DIR}/findings/static-analysis.json` |
   | `{{CODE_REVIEW_FINDINGS}}`     | `{OUTPUT_DIR}/findings/code-review.json`     |
   | `{{DEPENDENCY_FINDINGS}}`      | `{OUTPUT_DIR}/findings/dependencies.json`    |

4. Dispatch the prepared prompt as an Agent subagent. Description: `"Run Phase 6 validation"`.
5. Wait for the subagent to return.
6. Use the Read tool to load `{OUTPUT_DIR}/validated-findings.json`.
   - **If the file exists and is valid JSON:** store its contents as `VALIDATED_FINDINGS`. Append a `completed` log entry.
   - **If the file is missing or invalid:** store `VALIDATED_FINDINGS` as `{}`. Append a `failed` log entry. Do not abort.

---

## Step 8 — Phase 7: Reporting

**Goal:** Produce the final markdown and SARIF report files in `{OUTPUT_DIR}/`.

1. Use the Read tool to read `{SKILL_DIR}/phases/reporting.md`.
2. Perform these replacements:
   - Replace `{{VALIDATED_FINDINGS}}` with the contents of `VALIDATED_FINDINGS`.
   - Replace `{{REPO_PROFILE}}` with the contents of `REPO_PROFILE`.
   - Replace `{{THREAT_MODEL}}` with the contents of `THREAT_MODEL`.
   - Replace `{{OUTPUT_DIR}}` with the actual value of `OUTPUT_DIR`.
   - Replace `{{SERVICES}}` with the `services` array from `REPO_PROFILE` (extracted as a JSON array string). If `is_monorepo` is `false` in the repo profile, replace `{{SERVICES}}` with `[]`.
3. Dispatch the prepared prompt as an Agent subagent. Description: `"Run Phase 7 reporting"`.
4. Wait for the subagent to return.
5. Append a `completed` or `failed` log entry to `scan.log`.

---

## Step 9 — Present Results

After Phase 8 completes, read `{OUTPUT_DIR}/validated-findings.json` and extract the summary section. Then output the following to the user:

```
vuln-scan complete for: {TARGET_PATH}

Findings summary:
  Critical : 
  High     : 
  Medium   : 
  Low      : 
  Total    : 

Reports written to:
  {OUTPUT_DIR}/SECURITY_REPORT.md
  {OUTPUT_DIR}/report.sarif

Scan log: {OUTPUT_DIR}/scan.log
```

If the repo profile's `is_monorepo` is `true`, also display:

```
Service breakdown:
  {service_name}: {count} findings
  {service_name}: {count} findings
  shared ({shared_name}): {count} findings (affects: {consumers list})
```

Read the `by_service` counts from `validated-findings.json`'s summary section.

If `validated-findings.json` is absent or unparseable, omit the findings summary section and note that validation output was unavailable.

Append a final log entry to `scan.log`:

```json
{"ts": "", "phase": "coordinator", "event": "completed", "duration_s": }
```

---

## scan.log Format Reference

Every log entry is a single JSON object written as one line. Append entries with the Write or Bash tool (append mode). Never overwrite the log — only append.

```
{"ts": "", "phase": "", "event": "", ...context}
```

**Event types:**
- `start` — pipeline is beginning; include `"target": ""`
- `dispatched` — agent has been sent (optional, use for long phases)
- `completed` — phase finished successfully; include `"duration_s": `
- `failed` — phase produced no usable output; include `"reason": ""`
- `skipped` — phase was intentionally bypassed; include `"reason": ""`

**Phase names:** `coordinator`, `recon`, `threat-model`, `static-analysis`, `code-review`, `dependency-scan`, `validation`, `reporting`, `parallel-dispatch`

---

## Key Constraints

- **Never prompt the user** during execution. All decisions are defined in this document.
- **Never abort on phases 3–7 failures.** Partial results are always better than no results. Only Phase 1 (Recon) is a hard abort condition.
- **Skill directory resolution:** `{SKILL_DIR}` refers to the directory from which this SKILL.md was loaded. Phase prompts live in `{SKILL_DIR}/phases/`. When dispatching subagents, use absolute paths when reading phase files.
- **Template injection** is simple string replacement. Replace `{{PLACEHOLDER}}` literally with the substituted content. Do not interpret or transform the content.
- **Output directory** is always `{OUTPUT_DIR}/`. All phase output files are written there by the subagents — the coordinator only reads them.
- **Write boundary:** Subagents must only write files inside `{OUTPUT_DIR}/`. If a subagent writes or modifies any file outside this directory, it must revert the change (e.g., `git checkout -- `) and log a violation entry to `scan.log`: `{"ts": "", "phase": "", "event": "write_violation", "file": "", "action": "reverted"}`.
- **Error messages** go to `scan.log` as JSON entries. Only surface errors to the user on a hard abort (Phase 1 failure) or in the final summary.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [thapr0digy](https://github.com/thapr0digy)
- **Source:** [thapr0digy/skills](https://github.com/thapr0digy/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-thapr0digy-skills-vuln-scan
- Seller: https://agentstack.voostack.com/s/thapr0digy
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
