| name | attack-scenario-gen |
| description | Generates structured attack scenarios from Nuclei scan results (JSONL) by mapping CWE → CAPEC → ATT&CK and producing JSON output for dashboard visualization. |
| categories | ["security","attack-scenario"] |
| dependencies | ["python3"] |
Attack Scenario Generator
1. Local Knowledge Base
- Skill Root:
./scripts/
- DB Root:
./db/
- Scan Results:
/home/node/.openclaw/workspace/results/
2. Execution Flow
Step 1: Parse JSONL
Always re-run this step. Delete parsed_findings.json if it exists before running.
Run parse_jsonl.py to extract confirmed fields from scan result JSONL files.
python3 ./scripts/parse_jsonl.py \
../../results/findings.jsonl \
../../results/parsed_findings.json
Extracted fields per finding:
template_id, name, severity
cwe_ids (from info.classification.cwe-id)
cwe_names (from info.metadata.cwe-name)
matched_at, request, extracted_results, status_code
Findings without cwe_ids are automatically skipped.
Step 2: Map CWE → CAPEC → ATT&CK
Always re-run this step. Delete mapped_findings.json if it exists before running.
Run map_cwe_to_attack.py to map each finding to CAPEC and ATT&CK.
python3 ./scripts/map_cwe_to_attack.py \
/home/node/.openclaw/workspace/results/parsed_findings.json \
/home/node/.openclaw/workspace/results/mapped_findings.json
If attack_mapping_available is false after running the script, it means the DB has no ATT&CK entry for that CAPEC. Do NOT infer or hallucinate technique IDs. Leave attack_mapping as an empty array and use only capec_descriptions and cwe_names for the scenario steps.
Step 3: Generate Attack Scenarios
Read mapped_findings.json directly and generate attack scenarios yourself as the AI agent.
Do NOT use any external script or API call for this step.
For each unique template_id in the findings, generate a scenario JSON object using your own reasoning based on the CWE, CAPEC, and ATT&CK mapping data provided.
For each finding, generate a JSON object with this exact structure:
{
"scenario_id": "SCN-{template_id}",
"template_id": "",
"name": "",
"severity": "",
"cwe_ids": [],
"cwe_names": [],
"capec_ids": [],
"capec_descriptions": {},
"attack_mapping": [],
"attack_mapping_available": false,
"matched_at": "",
"status_code": null,
"extracted_results": [],
"scenario": {
"title": "short attack scenario title",
"preconditions": ["condition1", "condition2"],
"steps": [
{
"step": 1,
"tactic_id": "TA00XX or empty",
"tactic_name": "tactic name or empty",
"technique_id": "TXXXX or empty",
"technique_name": "technique name or empty",
"description": "what the attacker does"
}
],
"impact": "what damage can be done",
"remediation": "how to fix"
}
}
Rules:
- Deduplicate by
template_id — generate one scenario per unique template. When the same template_id appears multiple times (found on different URLs), keep the entry with the most data (non-empty extracted_results preferred). If equal, use the first occurrence. Set matched_at to the URL from the selected entry.
- Check
attack_mapping_available field before generating steps.
- If
attack_mapping_available is true, MUST use attack_mapping values for tactic_id, tactic_name, technique_id, technique_name in each step. Do NOT override with your own knowledge.
- Only if
attack_mapping_available is false, infer tactic/technique from capec_descriptions and cwe_names as fallback.
- Use English for all scenario fields
- Save all scenarios as a JSON array to
/home/node/.openclaw/workspace/results/scenarios.json
- The following fields MUST be copied exactly from
mapped_findings.json without any modification, summarization, or truncation:
template_id, name, severity, cwe_ids, cwe_names, capec_ids, capec_descriptions, attack_mapping, attack_mapping_available, matched_at, status_code, extracted_results
- Do NOT infer, guess, summarize, shorten, or modify these fields in any way. Copy the raw value as-is, including full description strings.
capec_descriptions values must be the complete, untruncated strings from the source file. Do NOT replace with names or summaries.
status_code must be copied as an integer (e.g., 200). If the source value is null, leave it null — do NOT set it based on inference.
- If a value is empty or null in the source, leave it empty or null.
Step 4: Report
After saving scenarios.json, summarize in chat:
- Total scenarios generated
- List of
scenario_id, name, severity for each
- Any findings skipped and why
3. Notes
- Always delete existing output files before running scripts to ensure fresh results:
rm /home/node/.openclaw/workspace/results/parsed_findings.json
rm /home/node/.openclaw/workspace/results/mapped_findings.json
rm /home/node/.openclaw/workspace/results/scenarios.json
- Always check if
db/cwe_to_capec.json and db/capec_to_attack.json exist before running map script
- If DB files are missing, run: python3 ./scripts/build_mapping_db.py