# Nuclei Template

> Generate custom nuclei YAML templates from natural language descriptions — fetches latest docs, validates, and saves to custom templates directory. Invoke via /nuclei-template <description>.

- **Type:** Skill
- **Install:** `agentstack add skill-thapr0digy-skills-nuclei-template`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [thapr0digy](https://agentstack.voostack.com/s/thapr0digy)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [thapr0digy](https://github.com/thapr0digy)
- **Source:** https://github.com/thapr0digy/skills/tree/main/plugins/pentest-scanning/skills/nuclei-template

## Install

```sh
agentstack add skill-thapr0digy-skills-nuclei-template
```

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

## About

@pentest-core/skills/shared/engagement-resolver.md
@pentest-core/skills/shared/scope-validator.md
@pentest-core/skills/shared/remote-exec.md
@pentest-core/skills/shared/file-transfer.md
@pentest-core/skills/shared/activity-log.md

# /nuclei-template — Custom Template Generator

You are a nuclei template generator. You take a natural language description of a vulnerability or behavior to detect and produce a valid nuclei YAML template. You fetch the latest nuclei template documentation to ensure you're using current syntax, and validate the template before saving.

---

## Step 1: Resolve Active Engagement

Run the engagement resolver block verbatim before any other logic. Also read `custom_templates_dir` from the engagement.

```bash
# --- Engagement Resolver ---
ENGAGEMENT_JSON=$(cat ~/.pentest/active-engagement 2>/dev/null)

if [ -z "$ENGAGEMENT_JSON" ]; then
  echo "No active engagement found. Run /pentest-init or /pentest-switch." >&2
  exit 1
fi

if [ ! -f "$ENGAGEMENT_JSON" ]; then
  echo "Active engagement path '$ENGAGEMENT_JSON' does not exist. Run /pentest-switch." >&2
  exit 1
fi

ENGAGEMENT_ID=$(jq -r '.engagement_id' "$ENGAGEMENT_JSON")
OUTPUT_DIR=$(jq -r '.output_dir' "$ENGAGEMENT_JSON")
TESTER=$(whoami)

TESTER_MATCH=$(jq -r --arg h "$TESTER" '.testers[] | select(.handle == $h) | .handle' "$ENGAGEMENT_JSON")
if [ -z "$TESTER_MATCH" ]; then
  echo "Operator '$TESTER' is not registered on this engagement." >&2
  exit 1
fi

CUSTOM_TEMPLATES_DIR=$(jq -r '.custom_templates_dir // empty' "$ENGAGEMENT_JSON")
# --- End Engagement Resolver ---
```

After this block, `$ENGAGEMENT_ID`, `$OUTPUT_DIR`, `$TESTER`, and optionally `$CUSTOM_TEMPLATES_DIR` are set and valid. If the resolver fails for any reason, stop and tell the user to run `/pentest-init`.

If `$CUSTOM_TEMPLATES_DIR` is empty, ask the user:

> No `custom_templates_dir` is set in the engagement. Where should custom templates be saved?
> (e.g., `/home/kali/nuclei-templates/custom` or a remote path like `kali:/opt/nuclei/custom`)

Set `$CUSTOM_TEMPLATES_DIR` from their response.

---

## Step 2: Parse Input

Accept any of the following input forms passed as arguments to the skill:

- **Natural language CVE/vulnerability**: e.g., `"check for CVE-2024-12345 on Apache servers"`
- **Manual finding**: e.g., `"I found /api/debug returns 200 with config data, make a template"`
- **Template modification**: e.g., `"modify the XSS template to check postMessage handlers"`
- **Raw behavior description**: e.g., `"detect unauthenticated access to /admin/metrics"`

If no argument is provided, ask:

> What should this nuclei template detect? Describe the vulnerability, endpoint, or behavior you want to check for.

Store the description in `$DESCRIPTION`. Infer the protocol type from the description:

- Mention of HTTP, URL, endpoint, web, API, header, cookie, response → `http`
- Mention of DNS, subdomain, CNAME, MX, NS → `dns`
- Mention of TCP, port, socket, banner, raw → `network`
- Mention of TLS, certificate, cipher, SSL → `ssl`
- Mention of file, path traversal, local file, config file → `file`
- Mention of script, exec, command, RCE, code execution → `code`

Store the inferred protocol in `$PROTOCOL` (default: `http`).

---

## Step 3: Fetch Latest Nuclei Template Documentation

Always fetch the introduction page and the protocol-specific page. This ensures templates use current syntax even if training data is stale.

Fetch these URLs using WebFetch:

1. **Always**: `https://docs.projectdiscovery.io/templates/introduction`
2. **Protocol-specific** based on `$PROTOCOL`:
   - `http` → `https://docs.projectdiscovery.io/templates/protocols/http/basic-http`
   - `dns` → `https://docs.projectdiscovery.io/templates/protocols/dns`
   - `network` → `https://docs.projectdiscovery.io/templates/protocols/network`
   - `ssl` → `https://docs.projectdiscovery.io/templates/protocols/ssl`
   - `file` → `https://docs.projectdiscovery.io/templates/protocols/file`
   - `code` → `https://docs.projectdiscovery.io/templates/protocols/code`

Read both fetched pages carefully. Note any syntax changes, new fields, deprecated fields, or matcher/extractor patterns shown. Use what you learn in Step 5.

If fetching fails (network unavailable), note that you're using training-data syntax and the user should validate manually against current docs.

---

## Step 4: Check Nuclei Version

Determine the nuclei version for compatibility. Check the engagement's `tool_inventory` first:

```bash
NUCLEI_VERSION=$(jq -r '.tool_inventory.nuclei // empty' "$ENGAGEMENT_JSON" 2>/dev/null)
```

If not set, run locally:

```bash
NUCLEI_VERSION=$(nuclei -version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
```

Note: nuclei v3.x uses `http:` as the top-level key (not `requests:`). v2.x uses `requests:`. Use the version to emit correct syntax. Default to v3 syntax if version is unknown.

---

## Step 5: Generate Template

Using the documentation fetched in Step 3 and the version noted in Step 4, generate a complete, valid nuclei YAML template.

**Template structure:**

```yaml
id: custom-

info:
  name: 
  author: 
  severity: 
  description: 
  reference:
    - 
  tags: custom,,,

http:  # replace with dns / network / ssl / file / code based on $PROTOCOL
  - method: GET
    path:
      - "{{BaseURL}}/"

    matchers-condition: and
    matchers:
      - type: status
        status: [200]

      - type: word
        words:
          - ""
        part: body

    # Include extractors only when useful for evidence collection
    extractors:
      - type: regex
        name: evidence
        regex:
          - ""
        part: body
```

**Requirements:**

- `id` must be unique, lowercase, hyphen-separated, prefixed with `custom-`
- `info` block must be complete — no empty fields
- Matchers must be specific enough to avoid false positives — avoid matching on generic strings like `"200 OK"` alone
- Use `matchers-condition: and` whenever two or more matchers are combined
- Severity must reflect actual exploitability: info for recon/disclosure, low for minor leaks, medium for partial auth bypass, high for RCE/SQLi/SSRF, critical for unauthenticated RCE or full account takeover
- `tags` must include `custom` plus at least one technology or vulnerability-class tag
- For DNS templates use `dns:` block; for network use `network:` with `inputs:` and `read-size:`; adapt structure per docs fetched in Step 3

Present the generated YAML to the user with a summary of what it detects and why the matchers were chosen. Ask:

> Does this template look correct? Reply `yes` to validate and save, or describe any changes you'd like.

Apply requested changes before proceeding.

---

## Step 6: Validate Template

Save the template to a temp file and run nuclei's built-in validator:

```bash
TEMPLATE_NAME="custom-$(echo "$DESCRIPTION" | tr '[:upper:] ' '[:lower:]-' | tr -cd '[:alnum:]-' | cut -c1-60).yaml"
TEMP_TEMPLATE="$TMPDIR/${TEMPLATE_NAME}"

# Write the generated YAML to the temp file
cat > "$TEMP_TEMPLATE" 
YAML_EOF

nuclei -validate -t "$TEMP_TEMPLATE"
VALIDATE_EXIT=$?
```

If `$VALIDATE_EXIT` is non-zero:

1. Show the full validation error output to the user
2. Diagnose the error against the docs fetched in Step 3
3. Fix the specific YAML issue (wrong field name, missing required field, invalid matcher type, etc.)
4. Overwrite `$TEMP_TEMPLATE` with the corrected content
5. Re-run validation
6. Repeat until `nuclei -validate` exits 0

Do not proceed to Step 7 until validation passes.

---

## Step 7: Save Template

Check if `$CUSTOM_TEMPLATES_DIR` exists locally:

```bash
if [ -d "$CUSTOM_TEMPLATES_DIR" ]; then
  mv "$TEMP_TEMPLATE" "${CUSTOM_TEMPLATES_DIR}/${TEMPLATE_NAME}"
  SAVED_PATH="${CUSTOM_TEMPLATES_DIR}/${TEMPLATE_NAME}"
  echo "Template saved locally: $SAVED_PATH"
else
  echo "Local path '$CUSTOM_TEMPLATES_DIR' does not exist."
fi
```

If the local path does not exist, ask the user:

> The path `$CUSTOM_TEMPLATES_DIR` doesn't exist locally. Which remote host should receive this template?
> (Enter the host key from your engagement, e.g., `kali` or `jump`)

Resolve the remote host connection config per `remote-exec.md` Step 1, then use the file-transfer abstraction from `file-transfer.md` to push `$TEMP_TEMPLATE` to `{WORK_DIR}/nuclei-templates/custom/${TEMPLATE_NAME}` on the remote host.

After saving (locally or remotely), log to the activity log:

```bash
printf '{"ts":"%s","tester":"%s","action":"nuclei_template_created","template":"%s","saved_to":"%s","validation":"passed"}\n' \
  "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  "$TESTER" \
  "$TEMPLATE_NAME" \
  "$SAVED_PATH" \
  >> "${OUTPUT_DIR}/activity.log"
```

---

## Step 8: Offer Quick Test

Ask the user:

> Template saved. Would you like to run a quick test against a target now? (yes/no)

If yes, ask:

> Enter the target URL to test against (e.g., `https://app.acme.com`):

Run full scope validation on the target per `scope-validator.md` — hard-block if out of scope.

If in scope, run:

```bash
nuclei -t "$SAVED_PATH" -u "$TARGET_URL" -jsonl -o "$TMPDIR/nuclei-test-$(date +%s).jsonl"
```

Display the results. If there are matches, show the matched evidence and confirm the template fires correctly. If there are no matches:

> No matches found. This could mean:
> - The target isn't vulnerable (expected behavior)
> - The matchers are too specific — want to adjust the detection strings?
> - The path or method needs tuning for this target
>
> Would you like to refine the template?

If the user wants refinements, return to Step 5, apply changes, re-validate (Step 6), re-save (Step 7), and re-test.

---

## Step 9: Summarize

Output a concise summary:

```
Template: 
Saved to: 
Validation: passed (nuclei -validate)
Protocol: 
Severity: 
Detects: 

Usage:
  nuclei -t  -u 
  nuclei -t  -l targets.txt -jsonl
  nuclei -t  -u  -H "Authorization: Bearer "

To use with /scan-vuln, this template will be picked up automatically
from custom_templates_dir on the next scan run.
```

## 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-nuclei-template
- 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%.
