Files
Anthropic-Cybersecurity-Skills/skills/implementing-vulnerability-sla-breach-alerting/references/api-reference.md
T
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- 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
2026-03-19 13:26:49 +01:00

5.6 KiB

API Reference: Vulnerability SLA Breach Alerting

Libraries Used

Library Purpose
requests Slack webhook and Jira API integration
smtplib Send email alerts for SLA breaches
json Parse vulnerability and SLA data
datetime Calculate SLA deadlines and breach timing
email.mime.text Compose HTML email notifications

Installation

pip install requests

Alert Channels

Slack Webhook Alert

import requests
import os

SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]

def send_slack_alert(breaches):
    blocks = [
        {
            "type": "header",
            "text": {"type": "plain_text", "text": "SLA Breach Alert"}
        },
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": f"*{len(breaches)} vulnerabilities have breached SLA*",
            }
        },
    ]
    for breach in breaches[:10]:
        blocks.append({
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": (
                    f"*{breach['cve']}* — {breach['severity'].upper()}\n"
                    f"Host: `{breach['host']}` | Overdue: {breach['hours_overdue']}h\n"
                    f"Owner: {breach.get('owner', 'Unassigned')}"
                ),
            }
        })

    resp = requests.post(
        SLACK_WEBHOOK,
        json={"blocks": blocks},
        timeout=10,
    )
    return resp.status_code == 200

Email Alert (SMTP)

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

def send_email_alert(breaches, recipients):
    smtp_host = os.environ["SMTP_HOST"]
    smtp_port = int(os.environ.get("SMTP_PORT", "587"))
    smtp_user = os.environ["SMTP_USER"]
    smtp_pass = os.environ["SMTP_PASS"]

    msg = MIMEMultipart("alternative")
    msg["Subject"] = f"SLA Breach: {len(breaches)} vulnerabilities overdue"
    msg["From"] = smtp_user
    msg["To"] = ", ".join(recipients)

    html = "<h2>SLA Breach Report</h2><table border='1'>"
    html += "<tr><th>CVE</th><th>Severity</th><th>Host</th><th>Hours Overdue</th></tr>"
    for b in breaches:
        html += f"<tr><td>{b['cve']}</td><td>{b['severity']}</td>"
        html += f"<td>{b['host']}</td><td>{b['hours_overdue']}</td></tr>"
    html += "</table>"

    msg.attach(MIMEText(html, "html"))

    with smtplib.SMTP(smtp_host, smtp_port) as server:
        server.starttls()
        server.login(smtp_user, smtp_pass)
        server.sendmail(smtp_user, recipients, msg.as_string())

Jira Ticket Creation

JIRA_URL = os.environ["JIRA_URL"]
JIRA_AUTH = (os.environ["JIRA_USER"], os.environ["JIRA_TOKEN"])

def create_jira_ticket(breach):
    ticket = {
        "fields": {
            "project": {"key": os.environ.get("JIRA_PROJECT", "VULN")},
            "summary": f"SLA Breach: {breach['cve']} on {breach['host']}",
            "description": (
                f"Vulnerability {breach['cve']} ({breach['severity']}) "
                f"has breached its remediation SLA.\n\n"
                f"Host: {breach['host']}\n"
                f"Hours overdue: {breach['hours_overdue']}\n"
                f"Discovery date: {breach['discovery_date']}\n"
                f"SLA deadline: {breach['deadline']}\n\n"
                f"Required action: Remediate immediately."
            ),
            "issuetype": {"name": "Bug"},
            "priority": {"name": "Highest" if breach["severity"] == "critical" else "High"},
            "labels": ["sla-breach", "security", breach["severity"]],
        }
    }
    resp = requests.post(
        f"{JIRA_URL}/rest/api/2/issue",
        auth=JIRA_AUTH,
        json=ticket,
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()["key"]

SLA Breach Detection

from datetime import datetime, timedelta

SLA_TIERS = {
    "critical": timedelta(hours=24),
    "high": timedelta(hours=72),
    "medium": timedelta(days=30),
    "low": timedelta(days=90),
}

def detect_breaches(vulnerabilities):
    breaches = []
    now = datetime.now()
    for vuln in vulnerabilities:
        if vuln.get("remediated"):
            continue
        discovery = datetime.fromisoformat(vuln["discovery_date"])
        sla = SLA_TIERS.get(vuln["severity"].lower(), timedelta(days=90))
        deadline = discovery + sla
        if now > deadline:
            breaches.append({
                **vuln,
                "deadline": deadline.isoformat(),
                "hours_overdue": round((now - deadline).total_seconds() / 3600, 1),
            })
    return sorted(breaches, key=lambda b: b["hours_overdue"], reverse=True)

Orchestration

def run_sla_breach_alerting(vulnerabilities):
    breaches = detect_breaches(vulnerabilities)
    if not breaches:
        return {"breaches": 0, "alerts_sent": False}

    # Send alerts through all channels
    send_slack_alert(breaches)
    send_email_alert(breaches, os.environ.get("ALERT_RECIPIENTS", "").split(","))

    # Create Jira tickets for critical/high breaches only
    for breach in breaches:
        if breach["severity"] in ("critical", "high"):
            create_jira_ticket(breach)

    return {"breaches": len(breaches), "alerts_sent": True}

Output Format

{
  "run_time": "2025-01-15T10:00:00Z",
  "breaches_detected": 5,
  "alerts": {
    "slack": true,
    "email": true,
    "jira_tickets_created": 3
  },
  "breaches": [
    {
      "cve": "CVE-2024-21887",
      "severity": "critical",
      "host": "web-prod-01",
      "hours_overdue": 48.5,
      "deadline": "2025-01-13T10:00:00",
      "owner": "platform-team"
    }
  ]
}