mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-19 14:09:40 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,80 @@
|
||||
# API Reference: Threat Intelligence Report Generator Agent
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| jinja2 | >=3.1 | Template rendering for report generation |
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```bash
|
||||
python scripts/agent.py \
|
||||
--type operational \
|
||||
--data /cases/intel_data.json \
|
||||
--output-dir /cases/reports/ \
|
||||
--output report_meta.json
|
||||
```
|
||||
|
||||
## Report Types
|
||||
|
||||
| Type | Audience | Length | Frequency |
|
||||
|------|----------|--------|-----------|
|
||||
| strategic | C-suite, board, risk committee | 1-3 pages | Monthly/Quarterly |
|
||||
| operational | CISO, security directors, IR leads | 3-8 pages | Weekly |
|
||||
| tactical | SOC analysts, threat hunters | 1-2 pages | Daily/as-needed |
|
||||
| flash | All security staff | 1 page max | Urgent/as-needed |
|
||||
|
||||
## Functions
|
||||
|
||||
### `confidence_label(level) -> str`
|
||||
Maps confidence levels to ICD 203 language: "high" -> "We assess with high confidence", "medium" -> "We assess", "low" -> "Evidence suggests".
|
||||
|
||||
### `render_report(report_type, data) -> str`
|
||||
Renders a Jinja2 template with the provided data dict. Sets defaults for date, org, tlp.
|
||||
|
||||
### `validate_report_data(report_type, data) -> list`
|
||||
Validates required fields per report type. Returns list of error strings.
|
||||
|
||||
### `quality_check(rendered) -> list`
|
||||
Checks rendered report for: minimum length, TLP marker presence, unqualified confidence statements.
|
||||
|
||||
### `generate_report(report_type, data_path, output_dir) -> dict`
|
||||
Full pipeline: load JSON data, validate, render template, run quality checks, save Markdown output.
|
||||
|
||||
## TLP Levels
|
||||
|
||||
| Level | Sharing Scope |
|
||||
|-------|---------------|
|
||||
| RED | Named recipients only |
|
||||
| AMBER+STRICT | Organization only |
|
||||
| AMBER | Organization and trusted partners |
|
||||
| GREEN | Community-wide (ISAC, sector peers) |
|
||||
| CLEAR | Public distribution |
|
||||
|
||||
## Input Data Schema (Operational Example)
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "APT29 Campaign Targeting Financial Sector",
|
||||
"tlp": "AMBER",
|
||||
"org": "Security Operations Center",
|
||||
"executive_summary": ["APT29 actively targeting financial institutions..."],
|
||||
"adversary": {
|
||||
"name": "APT29 / Cozy Bear",
|
||||
"motivation": "Espionage",
|
||||
"sophistication": "Advanced",
|
||||
"target_sectors": ["Financial", "Government"]
|
||||
},
|
||||
"ttps": [{"tactic": "Initial Access", "technique_id": "T1566.001", "name": "Spearphishing", "observed": "2025-03-01"}],
|
||||
"key_judgments": [{"confidence": "high", "statement": "APT29 will continue targeting...", "evidence": "..."}],
|
||||
"recommendations": [{"priority": "Critical", "description": "...", "owner": "SOC", "timeframe": "24h", "details": "..."}],
|
||||
"iocs": [{"type": "domain", "value": "evil[.]com", "context": "C2", "confidence": "high"}]
|
||||
}
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
The agent produces two files:
|
||||
1. `{type}_report_{date}.md` - Rendered Markdown report with TLP headers
|
||||
2. `report_meta.json` - Metadata including validation errors and quality issues
|
||||
@@ -0,0 +1,289 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Threat intelligence report generation agent using jinja2 for template-based reporting."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
from jinja2 import Environment, BaseLoader
|
||||
except ImportError:
|
||||
sys.exit("jinja2 required: pip install jinja2")
|
||||
|
||||
TLP_LEVELS = {
|
||||
"RED": "Named recipients only; do not share outside the briefing room",
|
||||
"AMBER+STRICT": "Organization only; no sharing with partners or subsidiaries",
|
||||
"AMBER": "Organization and trusted partners with need-to-know",
|
||||
"GREEN": "Community-wide sharing (ISAC members, sector peers)",
|
||||
"CLEAR": "Public distribution; no restrictions",
|
||||
}
|
||||
|
||||
CONFIDENCE_MAP = {
|
||||
"high": "We assess with high confidence",
|
||||
"medium": "We assess",
|
||||
"low": "Evidence suggests",
|
||||
}
|
||||
|
||||
REPORT_TEMPLATES = {
|
||||
"strategic": """
|
||||
# {{ title }}
|
||||
**TLP:{{ tlp }}** | {{ date }} | {{ org }}
|
||||
|
||||
## Executive Summary
|
||||
{% for point in executive_summary %}
|
||||
- {{ point }}
|
||||
{% endfor %}
|
||||
|
||||
## Threat Landscape Overview
|
||||
{{ threat_overview }}
|
||||
|
||||
## Business Impact Assessment
|
||||
{{ impact_assessment }}
|
||||
|
||||
## Key Judgments
|
||||
{% for judgment in key_judgments %}
|
||||
{{ loop.index }}. {{ confidence_label(judgment.confidence) }} that {{ judgment.statement }}
|
||||
- Evidence: {{ judgment.evidence }}
|
||||
{% endfor %}
|
||||
|
||||
## Recommended Strategic Actions
|
||||
{% for action in recommendations %}
|
||||
- **{{ action.priority }}** ({{ action.timeframe }}): {{ action.description }}
|
||||
{% endfor %}
|
||||
|
||||
## Intelligence Gaps
|
||||
{% for gap in intelligence_gaps %}
|
||||
- {{ gap }}
|
||||
{% endfor %}
|
||||
|
||||
---
|
||||
Classification: TLP:{{ tlp }} - {{ tlp_description }}
|
||||
""",
|
||||
"operational": """
|
||||
# {{ title }}
|
||||
**TLP:{{ tlp }}** | {{ date }} | {{ org }}
|
||||
|
||||
## Executive Summary
|
||||
{% for point in executive_summary %}
|
||||
- {{ point }}
|
||||
{% endfor %}
|
||||
|
||||
## Active Campaign Analysis
|
||||
### Adversary Profile
|
||||
- **Name**: {{ adversary.name }}
|
||||
- **Motivation**: {{ adversary.motivation }}
|
||||
- **Sophistication**: {{ adversary.sophistication }}
|
||||
- **Target Sectors**: {{ adversary.target_sectors | join(', ') }}
|
||||
|
||||
### TTPs (MITRE ATT&CK)
|
||||
| Tactic | Technique ID | Technique Name | Observed |
|
||||
|--------|-------------|----------------|----------|
|
||||
{% for ttp in ttps %}
|
||||
| {{ ttp.tactic }} | {{ ttp.technique_id }} | {{ ttp.name }} | {{ ttp.observed }} |
|
||||
{% endfor %}
|
||||
|
||||
## Key Judgments
|
||||
{% for judgment in key_judgments %}
|
||||
{{ loop.index }}. {{ confidence_label(judgment.confidence) }} that {{ judgment.statement }}
|
||||
{% endfor %}
|
||||
|
||||
## Defensive Recommendations
|
||||
{% for action in recommendations %}
|
||||
### {{ action.priority }}: {{ action.description }}
|
||||
- **Owner**: {{ action.owner }}
|
||||
- **Timeframe**: {{ action.timeframe }}
|
||||
- **Details**: {{ action.details }}
|
||||
{% endfor %}
|
||||
|
||||
## IOC Summary
|
||||
| Type | Value | Context | Confidence |
|
||||
|------|-------|---------|------------|
|
||||
{% for ioc in iocs %}
|
||||
| {{ ioc.type }} | {{ ioc.value }} | {{ ioc.context }} | {{ ioc.confidence }} |
|
||||
{% endfor %}
|
||||
|
||||
---
|
||||
Classification: TLP:{{ tlp }} - {{ tlp_description }}
|
||||
""",
|
||||
"tactical": """
|
||||
# {{ title }}
|
||||
**TLP:{{ tlp }}** | {{ date }} | {{ org }}
|
||||
|
||||
## Summary
|
||||
{{ summary }}
|
||||
|
||||
## Indicators of Compromise
|
||||
| Type | Value | Context | Confidence |
|
||||
|------|-------|---------|------------|
|
||||
{% for ioc in iocs %}
|
||||
| {{ ioc.type }} | `{{ ioc.value }}` | {{ ioc.context }} | {{ ioc.confidence }} |
|
||||
{% endfor %}
|
||||
|
||||
## Detection Rules
|
||||
{% for rule in detection_rules %}
|
||||
### {{ rule.name }} ({{ rule.format }})
|
||||
```
|
||||
{{ rule.content }}
|
||||
```
|
||||
{% endfor %}
|
||||
|
||||
## MITRE ATT&CK Mapping
|
||||
{% for ttp in ttps %}
|
||||
- **{{ ttp.technique_id }}** - {{ ttp.name }}: {{ ttp.description }}
|
||||
{% endfor %}
|
||||
|
||||
## Patching Guidance
|
||||
{% for patch in patches %}
|
||||
- **{{ patch.cve }}**: {{ patch.description }} ({{ patch.severity }})
|
||||
{% endfor %}
|
||||
|
||||
---
|
||||
Classification: TLP:{{ tlp }} - {{ tlp_description }}
|
||||
""",
|
||||
"flash": """
|
||||
# FLASH: {{ title }}
|
||||
**TLP:{{ tlp }}** | {{ date }} | IMMEDIATE ACTION REQUIRED
|
||||
|
||||
## What Is Happening
|
||||
{{ what_is_happening }}
|
||||
|
||||
## Immediate Risk
|
||||
{{ immediate_risk }}
|
||||
|
||||
## What To Do Right Now
|
||||
{% for action in immediate_actions %}
|
||||
{{ loop.index }}. {{ action }}
|
||||
{% endfor %}
|
||||
|
||||
## Indicators of Compromise
|
||||
{% for ioc in iocs %}
|
||||
- {{ ioc.type }}: `{{ ioc.value }}`
|
||||
{% endfor %}
|
||||
|
||||
## Additional Context
|
||||
{{ context }}
|
||||
|
||||
---
|
||||
Classification: TLP:{{ tlp }} - {{ tlp_description }}
|
||||
Disseminated: {{ date }}
|
||||
""",
|
||||
}
|
||||
|
||||
|
||||
def confidence_label(level: str) -> str:
|
||||
"""Map confidence level to ICD 203 language."""
|
||||
return CONFIDENCE_MAP.get(level.lower(), "Evidence suggests")
|
||||
|
||||
|
||||
def render_report(report_type: str, data: dict) -> str:
|
||||
"""Render a threat intelligence report from template and data."""
|
||||
template_str = REPORT_TEMPLATES.get(report_type)
|
||||
if not template_str:
|
||||
raise ValueError(f"Unknown report type: {report_type}. Available: {list(REPORT_TEMPLATES.keys())}")
|
||||
|
||||
data.setdefault("date", datetime.utcnow().strftime("%Y-%m-%d"))
|
||||
data.setdefault("org", "Security Operations")
|
||||
data.setdefault("tlp", "AMBER")
|
||||
data["tlp_description"] = TLP_LEVELS.get(data["tlp"], "")
|
||||
|
||||
env = Environment(loader=BaseLoader())
|
||||
env.globals["confidence_label"] = confidence_label
|
||||
template = env.from_string(template_str)
|
||||
return template.render(**data)
|
||||
|
||||
|
||||
def validate_report_data(report_type: str, data: dict) -> List[str]:
|
||||
"""Validate that required fields are present for the report type."""
|
||||
errors = []
|
||||
required_all = ["title", "tlp"]
|
||||
for field in required_all:
|
||||
if field not in data:
|
||||
errors.append(f"Missing required field: {field}")
|
||||
if data.get("tlp") and data["tlp"] not in TLP_LEVELS:
|
||||
errors.append(f"Invalid TLP level: {data['tlp']}. Valid: {list(TLP_LEVELS.keys())}")
|
||||
|
||||
type_required = {
|
||||
"strategic": ["executive_summary", "threat_overview", "key_judgments", "recommendations"],
|
||||
"operational": ["executive_summary", "adversary", "ttps", "recommendations"],
|
||||
"tactical": ["summary", "iocs"],
|
||||
"flash": ["what_is_happening", "immediate_risk", "immediate_actions"],
|
||||
}
|
||||
for field in type_required.get(report_type, []):
|
||||
if field not in data:
|
||||
errors.append(f"Missing field for {report_type} report: {field}")
|
||||
return errors
|
||||
|
||||
|
||||
def quality_check(rendered: str) -> List[str]:
|
||||
"""Run quality checks on rendered report."""
|
||||
issues = []
|
||||
if len(rendered) < 200:
|
||||
issues.append("Report is very short; may lack sufficient detail")
|
||||
if "TLP:" not in rendered:
|
||||
issues.append("Missing TLP classification marker")
|
||||
unqualified = 0
|
||||
for keyword in ["will", "is certain", "definitely", "undoubtedly"]:
|
||||
if keyword in rendered.lower():
|
||||
unqualified += 1
|
||||
if unqualified > 0:
|
||||
issues.append(f"Found {unqualified} statements that may need confidence qualifiers")
|
||||
return issues
|
||||
|
||||
|
||||
def generate_report(report_type: str, data_path: str, output_dir: str) -> dict:
|
||||
"""Load data, validate, render, and save the report."""
|
||||
with open(data_path, "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
validation_errors = validate_report_data(report_type, data)
|
||||
if validation_errors:
|
||||
logger.warning("Validation issues: %s", validation_errors)
|
||||
|
||||
rendered = render_report(report_type, data)
|
||||
quality_issues = quality_check(rendered)
|
||||
if quality_issues:
|
||||
logger.warning("Quality issues: %s", quality_issues)
|
||||
|
||||
report_filename = f"{report_type}_report_{datetime.utcnow().strftime('%Y%m%d')}.md"
|
||||
report_path = os.path.join(output_dir, report_filename)
|
||||
with open(report_path, "w", encoding="utf-8") as f:
|
||||
f.write(rendered)
|
||||
logger.info("Report saved to %s", report_path)
|
||||
|
||||
return {
|
||||
"report_type": report_type,
|
||||
"output_path": report_path,
|
||||
"tlp": data.get("tlp", "AMBER"),
|
||||
"validation_errors": validation_errors,
|
||||
"quality_issues": quality_issues,
|
||||
"rendered_length": len(rendered),
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Threat Intelligence Report Generator")
|
||||
parser.add_argument("--type", required=True, choices=list(REPORT_TEMPLATES.keys()),
|
||||
help="Report type: strategic, operational, tactical, flash")
|
||||
parser.add_argument("--data", required=True, help="Path to JSON data file with report content")
|
||||
parser.add_argument("--output-dir", default=".", help="Output directory")
|
||||
parser.add_argument("--output", default="report_meta.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
os.makedirs(args.output_dir, exist_ok=True)
|
||||
result = generate_report(args.type, args.data, args.output_dir)
|
||||
out_path = os.path.join(args.output_dir, args.output)
|
||||
with open(out_path, "w") as f:
|
||||
json.dump(result, f, indent=2)
|
||||
logger.info("Metadata saved to %s", out_path)
|
||||
print(json.dumps(result, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user