Skip to content
Back to skills

Automated Response

ASecurity

Automated remediation and containment patterns (endpoint isolation, IOC blocking with allowlists and expiry, alert correlation, threat intelligence feed updates) and a framework for deciding when an action can run automatically and when it needs human approval. Use when designing response playbooks or containment automation.

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 1, 2026
securitypythonrustgoreactnodeawsazuregitapidatabase

Works with

  • api

Security analysis

A100/100

Scanned October 1, 2026

npx -y skills add HermeticOrmus/LibreSecOps-Claude-Code --skill automated-response --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Automated Response?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Automated Response
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hermeticormus-automated-response/badge)](https://www.skillsdirectory.com/skills/hermeticormus-automated-response)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "automated-response"
description: "Automated remediation and containment patterns (endpoint isolation, IOC blocking with allowlists and expiry, alert correlation, threat intelligence feed updates) and a framework for deciding when an action can run automatically and when it needs human approval. Use when designing response playbooks or containment automation."
---

# Automated Response

> Automated remediation patterns, containment actions, and the decision framework for when to automate versus when to require human approval.

## Knowledge Base

### The Automation Decision Framework

Not every action should be automated. The decision depends on three factors:

**Reversibility**: Can the action be undone easily? Blocking an IP is reversible (unblock it). Deleting data is not. Reversible actions are better candidates for automation.

**Blast radius**: What is the worst-case impact if the automation acts on a false positive? Isolating one endpoint is limited blast radius. Blocking a CDN IP range affects thousands of users.

**Confidence**: How certain is the detection that triggered the action? A verified IOC from multiple threat feeds warrants automated response. A single low-confidence alert does not.

```
Automation Decision Matrix:

                    High Confidence    Low Confidence
                   ┌─────────────────┬─────────────────┐
  Reversible,      │ AUTOMATE        │ AUTOMATE with   │
  Low Blast Radius │ (no approval)   │ approval gate   │
                   ├─────────────────┼─────────────────┤
  Irreversible OR  │ AUTOMATE with   │ DO NOT          │
  High Blast Radius│ approval gate   │ AUTOMATE        │
                   └─────────────────┴─────────────────┘
```

### Common Automated Response Actions

| Action | Tool | Reversibility | Blast Radius | Typical Approval |
|--------|------|--------------|-------------|-----------------|
| Block IP at firewall | Palo Alto, Fortinet API | Reversible | Low (single IP) | Auto for known-malicious |
| Isolate endpoint | CrowdStrike, SentinelOne API | Reversible | Medium (user impacted) | Approval required |
| Disable user account | Okta, Azure AD API | Reversible | Medium (user impacted) | Approval required |
| Quarantine email | M365, Proofpoint API | Reversible | Low (single email) | Auto for confirmed phishing |
| Block domain at DNS | DNS firewall API | Reversible | Low-Medium | Auto for known-malicious |
| Kill process | EDR API | Irreversible (process state lost) | Low | Auto for known malware |
| Delete file | EDR API, endpoint script | Irreversible | Low | Approval required |
| Reset password | IAM API | Partially reversible | Medium | Approval required |
| Revoke sessions | IAM API | Reversible (re-auth) | Medium | Auto for confirmed compromise |

### Containment Timing

Research consistently shows that containment speed is the strongest predictor of breach cost reduction.

```
Timeline of automated vs. manual response:

Automated (SOAR):
  Alert ──(seconds)──> Enrichment ──(seconds)──> Triage ──(seconds)──> Containment
  Total: 1-5 minutes

Manual:
  Alert ──(minutes)──> Analyst sees alert ──(minutes)──> Investigation ──(minutes)──> Containment
  Total: 30-120 minutes (often hours if after-hours)

After-hours manual:
  Alert ──(hours)──> Analyst paged ──(minutes)──> Investigation ──(minutes)──> Containment
  Total: 1-4 hours

The gap between automated and manual response is where damage accumulates.
```

## Patterns

### Pattern 1: Endpoint Containment Playbook

```python
"""
Playbook: Automated Endpoint Containment
Trigger: EDR alert with high confidence malware detection
Approval: Required for production servers, auto for workstations
"""

async def contain_endpoint(alert: dict) -> dict:
    """Orchestrate endpoint containment."""

    endpoint_id = alert['endpoint_id']
    hostname = alert['hostname']

    # Step 1: Gather context (parallel)
    asset_info, user_info, recent_alerts = await asyncio.gather(
        get_asset_info(hostname),
        get_user_info(alert.get('username')),
        get_recent_alerts(endpoint_id, hours=24),
    )

    # Step 2: Determine if approval is needed
    needs_approval = (
        asset_info.get('criticality') in ['critical', 'high'] or
        asset_info.get('type') == 'server' or
        user_info.get('is_executive', False)
    )

    # Step 3: Request approval if needed, otherwise auto-contain
    if needs_approval:
        approval = await request_approval(
            channel='#soc-approvals',
            message=f"Contain {hostname}? Asset: {asset_info['type']}, "
                    f"User: {alert.get('username')}, "
                    f"Detection: {alert['detection_name']}",
            timeout_minutes=15,
            escalate_to='on-call-manager'
        )
        if not approval.approved:
            return {'action': 'pending', 'reason': 'Approval denied or timed out'}

    # Step 4: Execute containment
    containment_result = await isolate_endpoint(
        endpoint_id=endpoint_id,
        allow_dns=True,     # Allow DNS for troubleshooting
        allow_dhcp=True,    # Keep network lease
        note=f"Auto-contained: {alert['detection_name']} "
             f"(Alert ID: {alert['alert_id']})"
    )

    # Step 5: Additional containment actions
    if alert.get('username'):
        await revoke_user_sessions(alert['username'])

    # Step 6: Create incident and notify
    incident = await create_incident(
        title=f"Malware containment: {hostname}",
        severity=alert.get('severity', 'high'),
        description=f"Endpoint {hostname} auto-contained due to "
                    f"{alert['detection_name']}. "
                    f"User sessions revoked for {alert.get('username')}.",
        artifacts={
            'alert': alert,
            'asset': asset_info,
            'containment': containment_result,
        }
    )

    await notify_stakeholders(
        channels=['#soc-alerts', '#it-ops'],
        message=f"Endpoint {hostname} contained. "
                f"Incident: {incident['id']}. "
                f"User {alert.get('username')} sessions revoked."
    )

    return {
        'action': 'contained',
        'endpoint': hostname,
        'incident_id': incident['id'],
        'containment_result': containment_result,
    }
```

### Pattern 2: IOC Blocking Playbook

```python
"""
Playbook: Automated IOC Blocking
Trigger: Threat intelligence feed or analyst submission
Risk: Low-Medium (reversible, but false positive blocks legitimate traffic)
"""

async def block_ioc(ioc: dict) -> dict:
    """Block a confirmed malicious IOC across security controls."""

    ioc_type = ioc['type']  # ip, domain, hash, url
    ioc_value = ioc['value']
    confidence = ioc.get('confidence', 'medium')

    # Step 1: Validate IOC
    if not validate_ioc_format(ioc_type, ioc_value):
        return {'action': 'rejected', 'reason': 'Invalid IOC format'}

    # Step 2: Check against allowlist (prevent blocking critical infrastructure)
    if await is_allowlisted(ioc_value):
        await notify_analyst(
            f"IOC {ioc_value} matches allowlist. Manual review required."
        )
        return {'action': 'blocked_by_allowlist', 'ioc': ioc_value}

    # Step 3: Check for blast radius
    blast_radius = await assess_blast_radius(ioc_type, ioc_value)
    if blast_radius['affected_users'] > 100:
        approval = await request_approval(
            message=f"Blocking {ioc_value} would affect "
                    f"{blast_radius['affected_users']} users. Approve?",
            timeout_minutes=30
        )
        if not approval.approved:
            return {'action': 'pending_approval', 'blast_radius': blast_radius}

    # Step 4: Block across security controls
    results = {}

    if ioc_type == 'ip':
        results['firewall'] = await block_ip_firewall(ioc_value)
        results['siem_watchlist'] = await add_to_siem_watchlist(ioc_value, 'ip')

    elif ioc_type == 'domain':
        results['dns_firewall'] = await block_domain_dns(ioc_value)
        results['proxy'] = await block_domain_proxy(ioc_value)
        results['siem_watchlist'] = await add_to_siem_watchlist(ioc_value, 'domain')

    elif ioc_type == 'hash':
        results['edr_block'] = await block_hash_edr(ioc_value)
        results['siem_watchlist'] = await add_to_siem_watchlist(ioc_value, 'hash')

    # Step 5: Set expiration (IOC blocks should not be permanent)
    expiration_days = {'high': 90, 'medium': 30, 'low': 7}
    await schedule_unblock(
        ioc_value,
        days=expiration_days.get(confidence, 30),
        review_required=True
    )

    # Step 6: Log and document
    await log_block_action(
        ioc=ioc,
        results=results,
        expiration=expiration_days.get(confidence, 30),
        source=ioc.get('source', 'unknown')
    )

    return {'action': 'blocked', 'ioc': ioc_value, 'results': results}
```

### Pattern 3: Alert Fatigue Reduction

```python
"""
Playbook: Alert Deduplication and Correlation
Reduces alert fatigue by grouping related alerts into incidents.
"""

async def correlate_alerts(new_alert: dict) -> dict:
    """Check if new alert belongs to an existing incident."""

    # Look for related alerts in the last 24 hours
    related = await find_related_alerts(
        new_alert,
        lookback_hours=24,
        correlation_fields=[
            'src_ip',
            'dest_ip',
            'username',
            'hostname',
            'detection_name',
        ]
    )

    if related['matches']:
        # Add to existing incident instead of creating new alert
        existing_incident = related['matches'][0]['incident_id']
        await add_alert_to_incident(existing_incident, new_alert)
        await update_incident_severity(existing_incident)  # May escalate

        return {
            'action': 'correlated',
            'incident_id': existing_incident,
            'related_alert_count': len(related['matches']),
            'new_alert_created': False
        }

    # No correlation -- create new incident
    incident = await create_incident_from_alert(new_alert)

    return {
        'action': 'new_incident',
        'incident_id': incident['id'],
        'new_alert_created': True
    }
```

### Pattern 4: Scheduled Threat Intelligence Update

```python
"""
Playbook: Automated Threat Intelligence Processing
Trigger: Schedule (every 6 hours)
Purpose: Ingest, deduplicate, and operationalize threat feeds
"""

async def process_threat_feeds():
    """Pull and process all configured threat feeds."""

    feeds = [
        {'name': 'AlienVault OTX', 'type': 'otx', 'url': '...'},
        {'name': 'Abuse.ch URLhaus', 'type': 'csv', 'url': '...'},
        {'name': 'CISA Known Exploited', 'type': 'json', 'url': '...'},
        {'name': 'Internal TI Platform', 'type': 'stix', 'url': '...'},
    ]

    for feed in feeds:
        try:
            # Fetch
            raw_data = await fetch_feed(feed)

            # Normalize to STIX format
            normalized = normalize_to_stix(raw_data, feed['type'])

            # Deduplicate against existing IOC database
            new_iocs = await deduplicate(normalized)

            # Score by confidence and relevance
            scored = score_iocs(new_iocs, organization_context)

            # High-confidence IOCs: auto-deploy to security controls
            high_confidence = [i for i in scored if i['confidence'] >= 0.8]
            for ioc in high_confidence:
                await block_ioc(ioc)  # Uses the IOC blocking playbook

            # Medium-confidence: add to watchlist (alert but do not block)
            medium_confidence = [i for i in scored if 0.5 <= i['confidence'] < 0.8]
            for ioc in medium_confidence:
                await add_to_siem_watchlist(ioc)

            # Log stats
            await log_feed_processing(
                feed=feed['name'],
                total=len(raw_data),
                new=len(new_iocs),
                blocked=len(high_confidence),
                watchlisted=len(medium_confidence),
            )

        except Exception as e:
            await alert_on_feed_failure(feed['name'], str(e))
```

## Anti-Patterns

- **Automating containment without blast radius checks**: Automatically blocking an IP that turns out to be a CDN node (Cloudflare, AWS) can take down the business. Always check against an allowlist of critical infrastructure IPs and domains.
- **Permanent IOC blocks**: Threat infrastructure changes. An IP that is malicious today may be reassigned to a legitimate service tomorrow. All blocks should have expiration dates with review requirements.
- **Automation without observability**: If you cannot see what your automation is doing (what it blocked, what it allowed, what errors occurred), you cannot trust it and you cannot debug it.
- **Cascading automation without circuit breakers**: One false positive triggering a chain of automated responses (block IP, isolate endpoint, disable account, page management) is an automation catastrophe. Include circuit breakers that pause automation when action volume exceeds thresholds.
- **Automating the wrong things first**: Automating rare, complex scenarios provides little value. Automate high-volume, low-complexity tasks first (enrichment, triage routing, known-bad blocking).
- **No rollback capability**: Every automated action should have a documented and tested rollback procedure. Automation without rollback is a one-way street toward outages.

## References

- NIST SP 800-61 Rev 2 (Incident Handling): https://csrc.nist.gov/publications/detail/sp/800-61/rev-2/final
- OASIS CACAO Security Playbooks: https://docs.oasis-open.org/cacao/security-playbooks/v2.0/security-playbooks-v2.0.html
- FIRST CSIRT Services Framework: https://www.first.org/standards/frameworks/csirts/csirt_services_framework_v2.1
- RE&CT Framework (Response Actions): https://atc-project.github.io/atc-react/
- Palantir Alert and Detection Strategy Framework: https://blog.palantir.com/alerting-and-detection-strategy-framework-52dc33722f

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…