Guide · AWS Security Hub · Automation Rules
AWS Security Hub Automation Rules — Auto-Triage, Suppression, Severity Overrides for MCP Servers
Security Hub automation rules evaluate every incoming and updated finding against a set of conditions and, when matched, apply finding field updates — changing severity labels, workflow states, notes, or custom fields — without requiring a Lambda function or EventBridge rule. For MCP server operators the highest-value use case is automatic suppression of low-signal findings from known-safe sources: if your test environment accounts generate hundreds of EC2 findings that you have accepted as risk, an automation rule can set Workflow.Status = SUPPRESSED and add an explanatory note on every matching finding automatically. The critical architectural point: automation rules update finding metadata within Security Hub. They do not trigger external actions like sending a Slack message, isolating a resource, or creating a JIRA ticket. For those outcomes, combine automation rules (to normalize finding state) with EventBridge rules that react to Security Hub finding events (to execute actions).
TL;DR
Automation rules match findings using ASFF field conditions (string, number, date comparators) and apply FINDING_FIELDS_UPDATE actions to update Severity.Label, Workflow.Status, Note, Confidence, or UserDefinedFields. Rules evaluate in ascending RuleOrder (1 = first); set IsTerminal: true to stop further rule evaluation on a match. Use automation rules for finding triage within Security Hub; use EventBridge for external responses. See Security Hub setup guide, findings API guide, and cross-account guide for related configuration.
Create an automation rule
Each rule has a name, description, evaluation order, conditions (what to match), and actions (what to update). Conditions are AND'd together; multiple values within a single condition field are OR'd.
# Rule 1: Auto-suppress LOW severity findings from dev/test accounts
# Matches any LOW finding from accounts tagged as non-production
aws securityhub create-automation-rule \
--rule-name "suppress-low-sev-dev-accounts" \
--description "Auto-suppress LOW severity findings in dev and test environments — accepted risk" \
--rule-order 100 \
--is-terminal true \
--rule-status ENABLED \
--criteria '{
"SeverityLabel": [{"Value": "LOW", "Comparison": "EQUALS"}],
"AwsAccountId": [
{"Value": "111111111111", "Comparison": "EQUALS"},
{"Value": "222222222222", "Comparison": "EQUALS"}
]
}' \
--actions '[{
"Type": "FINDING_FIELDS_UPDATE",
"FindingFieldsUpdate": {
"Workflow": {"Status": "SUPPRESSED"},
"Note": {
"Text": "Auto-suppressed: LOW severity finding in dev/test account — accepted risk per security policy 2026-09",
"UpdatedBy": "security-hub-automation"
}
}
}]'
# Rule 2: Escalate HIGH findings on production MCP endpoints to CRITICAL
# Matches HIGH severity findings on resources tagged Environment=production
aws securityhub create-automation-rule \
--rule-name "escalate-prod-mcp-to-critical" \
--description "Escalate HIGH findings on production MCP resources to CRITICAL for immediate paging" \
--rule-order 50 \
--is-terminal false \
--rule-status ENABLED \
--criteria '{
"SeverityLabel": [{"Value": "HIGH", "Comparison": "EQUALS"}],
"ResourceTags": [
{
"Key": "Environment",
"Value": "production",
"Comparison": "EQUALS"
},
{
"Key": "Service",
"Value": "mcp-server",
"Comparison": "EQUALS"
}
]
}' \
--actions '[{
"Type": "FINDING_FIELDS_UPDATE",
"FindingFieldsUpdate": {
"Severity": {"Label": "CRITICAL"},
"Note": {
"Text": "Severity escalated to CRITICAL: production MCP server resource — immediate response required",
"UpdatedBy": "security-hub-automation"
}
}
}]'
Rule evaluation order and terminal rules
When a finding arrives or is updated, Security Hub evaluates all enabled automation rules in ascending order by RuleOrder (1 evaluates before 1000). If a rule matches and has IsTerminal: true, evaluation stops — no subsequent rules are applied to that finding. If a rule matches but IsTerminal: false, evaluation continues to the next rule.
# List all automation rules with their order and status
aws securityhub list-automation-rules \
--query 'AutomationRulesMetadata[*].{Name:RuleName,Order:RuleOrder,Status:RuleStatus,Terminal:IsTerminal}'
# Recommended rule ordering for MCP server environments:
# Order 10-49: Critical escalations (NEVER terminal — let other rules also run)
# Order 50-99: Enrichment rules (add context, tags, notes — never terminal)
# Order 100-499: Standard suppression rules (terminal=true — stop after suppression)
# Order 500-999: Catch-all fallbacks
# Example: both rules below apply to a single HIGH prod finding
# Rule order 50 (is_terminal=false): escalates HIGH → CRITICAL for prod resources
# Rule order 200 (is_terminal=true): suppresses CRITICAL findings from approved scanner
#
# If finding comes from prod resource AND approved scanner:
# 1. Order 50 runs: severity escalated to CRITICAL, continues evaluation
# 2. Order 200 runs: CRITICAL + approved-scanner matches → workflow = SUPPRESSED, stops
# Result: finding escalated AND suppressed (scanner output accepted as known risk)
# Update rule order (re-priority without recreating)
aws securityhub update-automation-rules \
--update-automation-rules-request-items '[{
"RuleArn": "arn:aws:securityhub:us-east-1:123456789012:automation-rule/suppress-low-sev-dev-accounts",
"RuleOrder": 150
}]'
Condition types and comparators
Automation rule conditions use the same filter structure as GetFindings. Different ASFF fields support different comparator types.
# String comparators: EQUALS | PREFIX | NOT_EQUALS | PREFIX_NOT_EQUALS | CONTAINS | NOT_CONTAINS
# Number comparators: EQUALS | NOT_EQUALS | GT | GTE | LT | LTE
# Date comparators: Start, End (ISO 8601 date range)
# Match findings by generator type prefix (all GuardDuty findings)
aws securityhub create-automation-rule \
--rule-name "tag-guardduty-findings" \
--rule-order 10 \
--is-terminal false \
--rule-status ENABLED \
--criteria '{
"GeneratorId": [{"Value": "arn:aws:guardduty:", "Comparison": "PREFIX"}]
}' \
--actions '[{
"Type": "FINDING_FIELDS_UPDATE",
"FindingFieldsUpdate": {
"UserDefinedFields": {
"finding_source": "guardduty",
"requires_incident_response": "true"
}
}
}]'
# Match by finding type prefix
# criteria: {"Type": [{"Value": "TTPs/", "Comparison": "PREFIX"}]}
# Match by normalized severity number range (equivalent to CRITICAL: 76-100)
# criteria: {"SeverityNormalized": [{"Gte": 76, "Lte": 100}]}
# Match by resource type
# criteria: {"ResourceType": [{"Value": "AwsLambdaFunction", "Comparison": "EQUALS"}]}
# Match by specific finding title containing keyword
# criteria: {"Title": [{"Value": "credential", "Comparison": "CONTAINS"}]}
# Match by date — findings created in the last 24 hours
# criteria: {"CreatedAt": [{"Start": "2026-10-07T00:00:00Z", "End": "2026-10-08T23:59:59Z"}]}
| Condition field | Comparators | MCP automation use case |
|---|---|---|
| SeverityLabel | EQUALS, NOT_EQUALS | Suppress all INFORMATIONAL, escalate HIGH on prod |
| SeverityNormalized | GT, GTE, LT, LTE | Fine-grained escalation (e.g., normalize GuardDuty 7.5 differently from 8.9) |
| AwsAccountId | EQUALS, NOT_EQUALS | Apply different rules to dev vs prod accounts |
| ResourceTags | EQUALS, NOT_EQUALS (key+value) | Suppress findings on resources tagged Environment=test |
| GeneratorId | PREFIX, CONTAINS | Different rules for GuardDuty findings vs Inspector findings |
| ProductName | EQUALS, NOT_EQUALS | Source-specific rules (GuardDuty vs Inspector vs Macie) |
| Type | PREFIX, EQUALS | Rules targeting TTPs namespace vs Software and Config namespace |
| WorkflowStatus | EQUALS, NOT_EQUALS | Only re-process findings still in NEW state (avoid re-suppressing resolved findings) |
Automation rules vs EventBridge — choosing the right tool
Both automation rules and EventBridge react to Security Hub findings, but they have different capabilities and purposes. Most MCP server security pipelines use both together.
| Capability | Automation rules | EventBridge |
|---|---|---|
| Update finding fields (severity, workflow, notes) | Yes — primary use case | No — EventBridge triggers external actions, cannot write back to Security Hub findings directly |
| Call Lambda / send SNS notification / create JIRA ticket | No | Yes — EventBridge targets Lambda, SNS, SQS, Step Functions, etc. |
| Isolate compromised EC2 instance | No | Yes — EventBridge → Lambda → EC2 SG modification |
| React to finding severity changes | Yes — re-evaluates on any finding update | Yes — Security Hub sends EventBridge events on finding create/update |
| No-code / low-code configuration | Yes — JSON conditions, no Lambda required | No — typically requires Lambda or Step Functions for useful responses |
| Rate limits | None — processes all findings | EventBridge rule invocations subject to Lambda concurrency limits |
| Cross-account scope | Runs in each account; admin account rules apply to its own findings | Admin account EventBridge can receive all member account findings via aggregation |
# Example combined pipeline: automation rule + EventBridge
# Step 1: Automation rule adds UserDefinedField to mark high-priority findings
# (done above — tags CRITICAL findings with requires_incident_response=true)
# Step 2: EventBridge rule fires on Security Hub findings where that field is set
# EventBridge pattern:
{
"source": ["aws.securityhub"],
"detail-type": ["Security Hub Findings - Imported"],
"detail": {
"findings": {
"Severity": {"Label": ["CRITICAL"]},
"UserDefinedFields": {
"requires_incident_response": ["true"]
}
}
}
}
# EventBridge target: Lambda that creates PagerDuty incident + JIRA ticket + Slack alert
# The automation rule ran first (normalized severity, added context)
# EventBridge sees the final normalized finding with full context
Managing automation rules
# List all rules (metadata only — no conditions/actions)
aws securityhub list-automation-rules
# Get full rule details including conditions and actions
aws securityhub batch-get-automation-rules \
--automation-rules-arns '[
"arn:aws:securityhub:us-east-1:123456789012:automation-rule/suppress-low-sev-dev-accounts"
]'
# Disable a rule (preserves configuration, stops evaluation)
aws securityhub update-automation-rules \
--update-automation-rules-request-items '[{
"RuleArn": "arn:aws:securityhub:us-east-1:123456789012:automation-rule/suppress-low-sev-dev-accounts",
"RuleStatus": "DISABLED"
}]'
# Delete rules (permanently removes)
aws securityhub batch-delete-automation-rules \
--automation-rules-arns '[
"arn:aws:securityhub:us-east-1:123456789012:automation-rule/old-rule-name"
]'
# Automation rules do NOT retroactively apply to existing findings
# They only run when a finding is created or updated
# To retroactively suppress existing findings: use batch-update-findings with a GetFindings filter
Failure modes reference
| Failure | Symptom | Fix |
|---|---|---|
| Automation rule not applying to existing findings | Rule created but hundreds of existing findings unchanged | Rules only apply on finding create/update — use batch-update-findings to retroactively update existing findings matching the same criteria |
| Rule condition matches unintended findings | Rule suppresses more findings than expected | Check RuleOrder — earlier rule may be changing a field that a later rule depends on; use batch-get-automation-rules to review exact conditions; test with a restrictive AwsAccountId condition first |
| IsTerminal=true rule not stopping evaluation | Finding processed by multiple rules including ones after the terminal rule | Terminal=true only stops rules with higher RuleOrder — earlier rules (lower number) always run first; reorder rules so terminal rule runs before the ones you want to skip |
| Severity override not persisting | Rule sets severity to CRITICAL but finding shows original severity | A subsequent rule (higher RuleOrder, not terminal) may be overwriting the severity again; check all rules matching the same finding criteria; reorder or add IsTerminal=true |
| UserDefinedFields not appearing on finding | Rule action sets UserDefinedFields but finding doesn't show them | GetFindings response includes UserDefinedFields only when they have values; verify with GetFindings + filter on the specific finding ID; check BatchGetAutomationRules to confirm action definition is correct |