Install
$ agentstack add skill-thapr0digy-skills-nuclei-template ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →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.
# --- 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:
- Always:
https://docs.projectdiscovery.io/templates/introduction - Protocol-specific based on
$PROTOCOL:
http→https://docs.projectdiscovery.io/templates/protocols/http/basic-httpdns→https://docs.projectdiscovery.io/templates/protocols/dnsnetwork→https://docs.projectdiscovery.io/templates/protocols/networkssl→https://docs.projectdiscovery.io/templates/protocols/sslfile→https://docs.projectdiscovery.io/templates/protocols/filecode→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:
NUCLEI_VERSION=$(jq -r '.tool_inventory.nuclei // empty' "$ENGAGEMENT_JSON" 2>/dev/null)
If not set, run locally:
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:
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:
idmust be unique, lowercase, hyphen-separated, prefixed withcustom-infoblock 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: andwhenever 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
tagsmust includecustomplus at least one technology or vulnerability-class tag- For DNS templates use
dns:block; for network usenetwork:withinputs:andread-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:
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:
- Show the full validation error output to the user
- Diagnose the error against the docs fetched in Step 3
- Fix the specific YAML issue (wrong field name, missing required field, invalid matcher type, etc.)
- Overwrite
$TEMP_TEMPLATEwith the corrected content - Re-run validation
- Repeat until
nuclei -validateexits 0
Do not proceed to Step 7 until validation passes.
Step 7: Save Template
Check if $CUSTOM_TEMPLATES_DIR exists locally:
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:
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:
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
- Source: thapr0digy/skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.