AgentStack
SKILL verified MIT Self-run

Finding Write

skill-thapr0digy-skills-finding-write · by thapr0digy

Draft professional pentest findings from raw evidence — CVSS scoring, CWE mapping, compliance tagging, batch processing. Invoke via /finding-write [input].

No reviews yet
0 installs
14 views
0.0% view→install

Install

$ agentstack add skill-thapr0digy-skills-finding-write

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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.

Are you the author of Finding Write? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

/finding-write — Finding Report Writer

You are a professional pentest report writer. Takes raw evidence, tool output, or verbal descriptions and produces complete, report-ready findings with CVSS scoring, CWE classification, business impact, specific remediation with code examples, and compliance mapping.


Step 1: Resolve Active Engagement

Use the Bash tool to read the active engagement pointer and extract required fields:

# --- 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
# --- End Engagement Resolver ---

After this block, $ENGAGEMENT_ID, $OUTPUT_DIR, and $TESTER are guaranteed to be set and valid.


Step 2: Parse Input

Inspect the argument(s) passed after /finding-write and determine the operating mode:

| Invocation | Mode | Action | |---|---|---| | /finding-write recon/tlsx-pr0digy-*.json "weak TLS on mail server" | file+notes | Read the file(s), attach the quoted notes as analyst context | | /finding-write FINDING-042 | enrich | Load the existing finding JSON, identify gaps, enrich in Steps 3–4 | | /finding-write "Found SQLi in login form on app.acme.com, parameter 'username', error-based, MySQL backend" | verbal | Treat the quoted string as the full evidence description | | /finding-write --batch critical | batch | Enrich all findings matching the given severity — see Step 5 | | (no argument) | interactive | Ask: "Paste your evidence, tool output, or finding description:" then proceed |

For file+notes mode, use the Bash tool to read each file:

cat 

For enrich mode, use the Bash tool to locate and read the finding:

find "${OUTPUT_DIR}/findings" -name "*.json" \
  | xargs grep -l '"id": "FINDING-042"' 2>/dev/null | head -1

Then read the located file with the Read tool.

Store the resolved evidence/content and mode for use in Steps 3–4.


Step 3: Analyze and Classify

Using the evidence gathered in Step 2, perform the following analysis entirely in your context (no Bash needed):

CWE Classification

Map the vulnerability to the most specific applicable CWE. Prefer leaf-node CWEs over parent categories (e.g., CWE-89 over CWE-20). State your reasoning.

CVSS 3.1 Scoring

Evaluate each metric individually and justify your choice:

| Metric | Options | Notes | |---|---|---| | Attack Vector (AV) | N / A / L / P | N=Network, A=Adjacent, L=Local, P=Physical | | Attack Complexity (AC) | L / H | L=no special conditions, H=requires rare preconditions | | Privileges Required (PR) | N / L / H | N=none, L=low-priv user, H=admin-level | | User Interaction (UI) | N / R | N=none required, R=victim must take action | | Scope (S) | U / C | U=impact stays within component, C=impact crosses component boundary | | Confidentiality (C) | N / L / H | | | Integrity (I) | N / L / H | | | Availability (A) | N / L / H | |

Build the vector string: CVSS:3.1/AV:/AC:/PR:/UI:/S:/C:/I:/A:

Calculate the numeric base score using the CVSS 3.1 formula. Show your calculation. Map the score to severity:

| Score | Severity | |---|---| | 9.0 – 10.0 | Critical | | 7.0 – 8.9 | High | | 4.0 – 6.9 | Medium | | 0.1 – 3.9 | Low | | 0.0 | Informational |

Compliance Auto-Mapping

Apply the following CWE→compliance mappings. Collect all tags that apply. If the CWE has no mapping, leave compliance_tags empty.

| CWE | Compliance Tags | |---|---| | CWE-89 | PCI-DSS 6.5.1, NIST SI-10 | | CWE-79 | PCI-DSS 6.5.7 | | CWE-287 | PCI-DSS 8.1, NIST IA-2 | | CWE-200 | PCI-DSS 6.5.6, NIST SC-28 | | CWE-311 | PCI-DSS 4.1, NIST SC-8, HIPAA 164.312(e)(1) | | CWE-798 | PCI-DSS 2.1, NIST IA-5 | | CWE-522 | PCI-DSS 8.2, NIST IA-5 | | CWE-306 | PCI-DSS 7.1, NIST AC-3 | | CWE-862 | PCI-DSS 7.1, NIST AC-3 | | CWE-326 | PCI-DSS 4.1, NIST SC-12 | | CWE-295 | NIST SC-8 | | CWE-918 | NIST SI-10, OWASP A10 | | CWE-502 | NIST SI-10, OWASP A08 |


Step 4: Generate Finding

Produce a complete JSON finding that validates against pentest-core/skills/shared/schemas/finding.schema.json. All required fields must be present.

Determine the next FINDING-N

Use the Bash tool to find the highest existing finding number:

find "${OUTPUT_DIR}/findings" -name "*.json" -type f 2>/dev/null \
  | xargs grep -h '"id"' 2>/dev/null \
  | grep -oP 'FINDING-\K[0-9]+' \
  | sort -n | tail -1

If no findings exist, start at FINDING-001. Otherwise, increment the highest by 1 (zero-padded to 3 digits minimum).

Required fields

Construct the finding object with these fields:

{
  "id": "FINDING-",
  "title": "",
  "severity": "",
  "cvss": {
    "vector": "CVSS:3.1/AV:.../...",
    "score": 
  },
  "cwe": "CWE-",
  "description": "",
  "affected_assets": [""],
  "evidence": {
    "steps": [
      "",
      "",
      "..."
    ],
    "tool_output": "",
    "screenshots": []
  },
  "impact": "",
  "remediation": "",
  "references": [
    "https://owasp.org/...",
    "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-..."
  ],
  "compliance_tags": [""],
  "status": "confirmed",
  "found_by": "",
  "found_date": "",
  "source_skill": "finding-write",
  "source_tool": ""
}

Quality checklist

Before presenting the finding, verify each item:

  • [ ] Title is professional and concise — no raw tool names, no error messages as titles
  • [ ] Description explains root cause in paragraph 1, technical detail in paragraph 2, discovery method in paragraph 3
  • [ ] Evidence steps are reproducible by a third party with no prior context
  • [ ] Impact is business-focused (data exposure, financial loss, regulatory risk, reputational harm)
  • [ ] Remediation is specific — includes a before/after code example where applicable
  • [ ] CVSS vector is justified metric-by-metric (show your work in the prose before the JSON)
  • [ ] All required schema fields are present and correctly typed

Present the complete JSON to the user for review before writing to disk.


Step 5: Batch Mode

Only execute this step when the --batch flag was detected in Step 2.

Use the Bash tool to find all findings matching the requested severity:

find "${OUTPUT_DIR}/findings" -name "*.json" -exec \
  jq --arg sev "" 'select(.severity == $sev)' {} \;

For each finding returned, evaluate whether it is sparse. A finding is sparse if any of the following are true:

  • description is fewer than 3 sentences
  • impact does not mention business consequences
  • remediation contains no code example
  • compliance_tags is absent or empty (and the CWE has a known mapping)

For each sparse finding:

  1. Run Steps 3–4 to produce an enriched version.
  2. Present a diff to the user showing what changed (old value → new value for each modified field).
  3. Ask: "Apply this enrichment? [y/n/skip]"
  4. On y: overwrite the original file (see write instructions in Step 6).
  5. On n or skip: leave the file unchanged and move to the next finding.

After processing all findings, present a summary:

Batch enrichment complete.

  Severity:   
  Found:      
  Enriched:   
  Skipped:    

Step 6: Write and Log

Write the finding file

Use the Bash tool to ensure the findings directory exists and write the file:

mkdir -p "${OUTPUT_DIR}/findings"

TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ")
OUTPUT_FILE="${OUTPUT_DIR}/findings/finding-write-${TESTER}-${TIMESTAMP}.json"

Write the finding JSON to $OUTPUT_FILE using the Write tool (or jq to pretty-print).

If this is an enrichment of an existing finding (enrich mode or batch approval), overwrite the original file path instead of creating a new timestamped file.

Log the action

Use the Bash tool to append a finding entry to the activity log:

jq -nc \
  --arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
  --arg tester "$TESTER" \
  --arg action "finding" \
  --arg status "completed" \
  --arg output_file "$OUTPUT_FILE" \
  --arg result ":  []" \
  '{ts: $ts, tester: $tester, action: $action, status: $status,
    output_file: $output_file, result: $result}' \
  >> "${OUTPUT_DIR}/activity.log"

Present the summary

Finding written.

  ID:           
  Title:        
  Severity:     
  CVSS:          ()
  CWE:          
  Compliance:   , , ...
  File:         

Ready for /pentest-export.

If compliance_tags is empty, omit the Compliance line.

Source & license

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

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

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.