mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-12 06:04:56 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
157 lines
5.7 KiB
Python
157 lines
5.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Post-incident lessons learned analysis agent."""
|
|
|
|
import json
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
|
|
def analyze_incident_timeline(incident_data):
|
|
"""Analyze incident timeline for response gaps."""
|
|
gaps = []
|
|
if not incident_data:
|
|
return gaps
|
|
events = incident_data.get("timeline", [])
|
|
for i in range(1, len(events)):
|
|
prev_time = datetime.fromisoformat(events[i-1]["timestamp"])
|
|
curr_time = datetime.fromisoformat(events[i]["timestamp"])
|
|
delta_minutes = (curr_time - prev_time).total_seconds() / 60
|
|
if delta_minutes > 30:
|
|
gaps.append({
|
|
"between": f"{events[i-1]['action']} -> {events[i]['action']}",
|
|
"gap_minutes": round(delta_minutes),
|
|
"severity": "HIGH" if delta_minutes > 120 else "MEDIUM",
|
|
"recommendation": "Reduce response time with automated playbooks",
|
|
})
|
|
return gaps
|
|
|
|
|
|
def calculate_metrics(incident_data):
|
|
"""Calculate key incident response metrics."""
|
|
timeline = incident_data.get("timeline", [])
|
|
if len(timeline) < 2:
|
|
return {}
|
|
detect_time = None
|
|
contain_time = None
|
|
resolve_time = None
|
|
for event in timeline:
|
|
action = event.get("action", "").lower()
|
|
ts = datetime.fromisoformat(event["timestamp"])
|
|
if "detect" in action and not detect_time:
|
|
detect_time = ts
|
|
if "contain" in action and not contain_time:
|
|
contain_time = ts
|
|
if "resolve" in action or "close" in action:
|
|
resolve_time = ts
|
|
start = datetime.fromisoformat(timeline[0]["timestamp"])
|
|
metrics = {}
|
|
if detect_time:
|
|
metrics["mttd_minutes"] = round((detect_time - start).total_seconds() / 60)
|
|
if contain_time and detect_time:
|
|
metrics["mttc_minutes"] = round((contain_time - detect_time).total_seconds() / 60)
|
|
if resolve_time and detect_time:
|
|
metrics["mttr_minutes"] = round((resolve_time - detect_time).total_seconds() / 60)
|
|
return metrics
|
|
|
|
|
|
def generate_action_items(gaps, metrics):
|
|
"""Generate prioritized action items from analysis."""
|
|
items = []
|
|
if metrics.get("mttd_minutes", 0) > 60:
|
|
items.append({
|
|
"priority": "P1",
|
|
"area": "Detection",
|
|
"action": "Deploy automated detection rules to reduce MTTD below 30 minutes",
|
|
"owner": "SOC Engineering",
|
|
})
|
|
if metrics.get("mttc_minutes", 0) > 120:
|
|
items.append({
|
|
"priority": "P1",
|
|
"area": "Containment",
|
|
"action": "Implement automated containment playbook in SOAR platform",
|
|
"owner": "IR Team",
|
|
})
|
|
for gap in gaps:
|
|
if gap["severity"] == "HIGH":
|
|
items.append({
|
|
"priority": "P2",
|
|
"area": "Process",
|
|
"action": f"Address {gap['gap_minutes']}min gap in {gap['between']}",
|
|
"owner": "IR Manager",
|
|
})
|
|
items.append({
|
|
"priority": "P3",
|
|
"area": "Training",
|
|
"action": "Schedule tabletop exercise within 30 days based on incident scenario",
|
|
"owner": "Security Training",
|
|
})
|
|
return items
|
|
|
|
|
|
def generate_report_template():
|
|
"""Generate lessons learned report template."""
|
|
return {
|
|
"sections": [
|
|
{"title": "Executive Summary", "content": "Brief overview of incident and impact"},
|
|
{"title": "Incident Timeline", "content": "Chronological sequence of events"},
|
|
{"title": "Root Cause Analysis", "content": "Underlying cause identification"},
|
|
{"title": "What Went Well", "content": "Effective response actions"},
|
|
{"title": "What Needs Improvement", "content": "Gaps and failures identified"},
|
|
{"title": "Action Items", "content": "Prioritized remediation tasks with owners and deadlines"},
|
|
{"title": "Metrics", "content": "MTTD, MTTC, MTTR measurements"},
|
|
{"title": "Appendix", "content": "Supporting evidence, IOCs, detection rules"},
|
|
],
|
|
}
|
|
|
|
|
|
def run_analysis(incident_file):
|
|
"""Execute post-incident lessons learned analysis."""
|
|
print(f"\n{'='*60}")
|
|
print(f" POST-INCIDENT LESSONS LEARNED")
|
|
print(f" Generated: {datetime.utcnow().isoformat()} UTC")
|
|
print(f"{'='*60}\n")
|
|
|
|
incident_data = {}
|
|
if incident_file:
|
|
with open(incident_file, "r") as f:
|
|
incident_data = json.load(f)
|
|
|
|
metrics = calculate_metrics(incident_data)
|
|
print(f"--- RESPONSE METRICS ---")
|
|
for k, v in metrics.items():
|
|
print(f" {k}: {v} minutes")
|
|
|
|
gaps = analyze_incident_timeline(incident_data)
|
|
print(f"\n--- TIMELINE GAPS ({len(gaps)}) ---")
|
|
for g in gaps:
|
|
print(f" [{g['severity']}] {g['between']}: {g['gap_minutes']} min gap")
|
|
|
|
items = generate_action_items(gaps, metrics)
|
|
print(f"\n--- ACTION ITEMS ({len(items)}) ---")
|
|
for item in items:
|
|
print(f" [{item['priority']}] {item['area']}: {item['action']}")
|
|
|
|
template = generate_report_template()
|
|
print(f"\n--- REPORT SECTIONS ---")
|
|
for s in template["sections"]:
|
|
print(f" - {s['title']}")
|
|
|
|
return {"metrics": metrics, "gaps": gaps, "action_items": items, "template": template}
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Post-Incident Lessons Learned Agent")
|
|
parser.add_argument("--incident-file", help="Incident data JSON file")
|
|
parser.add_argument("--output", help="Save report to JSON file")
|
|
args = parser.parse_args()
|
|
|
|
report = run_analysis(args.incident_file)
|
|
if args.output:
|
|
with open(args.output, "w") as f:
|
|
json.dump(report, f, indent=2, default=str)
|
|
print(f"\n[+] Report saved to {args.output}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|