Threat Feed
Detect ACTIVE abuse patterns from documented 2025-2026 incidents - not just misconfigurations.
The Threat Feed (introduced in v2.2.0) is a separate detection pipeline from
the regular cloud-audit scan checks. Where regular checks ask "is this
configured securely?", threat patterns ask "does this look like an
incident already happened or is happening?"
Each pattern maps to a documented real-world abuse case from 2025-2026 (cryptomining campaigns, SES phishing, leaked-credential scanner activity, Bedrock AgentCore CVEs) and carries external research references on every finding.
Quick Start
```bash
Scan all 10 patterns
cloud-audit threat-feed
Show registered patterns + rules-pack version
cloud-audit threat-feed --list
Run a single pattern
cloud-audit threat-feed --pattern aws-tf-003
Multi-region
cloud-audit threat-feed --regions us-east-1,eu-west-1
Or use the regular scan with category filter (full JSON/SARIF/HTML output)
cloud-audit scan --categories threat -o json ```
The command exits with code 1 when any CRITICAL or HIGH finding is
detected (CI gate friendly), 0 otherwise.
Rules pack versioning
Threat patterns are versioned as a pack (THREAT_FEED_VERSION,
currently 2026-Q2). Operators can pin a known pack with
--threat-feed-version 2026-Q2 to get reproducible scans across releases
even if cloud-audit ships new patterns mid-pack.
Adding a new pattern to the pack is intentionally a minor-version event: detection logic keeps evolving as new abuse patterns emerge in the wild, but pinning lets you decide when to take the new signals.
The 10 patterns (rules pack 2026-Q2)
TF-001 - SES phishing setup precursor (MEDIUM/HIGH) — precursor
Detects SES email or domain identities verified within the last 14 days. Severity escalates to HIGH when BOTH conditions hold: the account has production sending enabled (out of SES sandbox) AND two or more recent verifications are present in the same scan. The escalation matches the burst pattern Wiz documented in September 2025: "adding multiple domains as verified identities using the CreateEmailIdentity API" in quick succession - one identity is normal onboarding, several at once is the campaign signature.
Backed by: Wiz September 2025 SES abuse research, BleepingComputer May 2026
TF-002 - Lambda Function URL persistence (HIGH/CRITICAL) — strong heuristic
Detects Lambda functions exposed via Function URL with AuthType=NONE.
Public Lambdas are a legitimate pattern (webhooks, public APIs) but they
are also a recurring post-compromise persistence mechanism. Escalates to
CRITICAL when the execution role grants admin-class permissions
(AdministratorAccess, IAMFullAccess, KMS PowerUser, SecretsManagerReadWrite,
S3FullAccess, EC2FullAccess). The Hacker News and The Register cryptomining
writeups document Lambda function creation during the campaign; they do
not specify Function URL configuration, so the connection here is the
broader public-Lambda persistence category rather than a 1:1 incident match.
Backed by: The Hacker News Dec 2025, The Register Dec 2025
TF-003 - AWS credential quarantine policy attached (CRITICAL) — confirmed signal
Detects IAM principals with AWSCompromisedKeyQuarantineV1, V2, or V3
attached. AWS automatically attaches these when its credential-exposure
detection identifies leaked access keys (typically a public GitHub commit).
Presence is a near-certain confirmation that AWS detected a credential leak.
Backed by: AWS managed policy reference, Permiso DetentionDodger
TF-004 - Leaked-credentials scanner UA in CloudTrail (CRITICAL) — strong heuristic
Detects sts:GetCallerIdentity calls in the last 24h whose userAgent
contains substrings characteristic of OFFENSIVE leaked-credentials discovery
scanners (trufflehog, gitleaks, noseyparker, secretscanner).
Defensive tools like Permiso CloudGrappler and DetentionDodger are
intentionally excluded - their UA in CloudTrail means a defender is
running them, not that the account is under attack.
Detection caveat: the pattern only catches scanners that surface a
recognisable user-agent. Many scanner runtimes (including TruffleHog when
invoked without --user-agent-suffix) fall back to default AWS SDK
user-agents which look identical to legitimate boto3 / aws-cli traffic.
TF-004 catches the careless attacker who let the UA leak; a careful
attacker reaching the same goal will not trigger it. Treat presence as
confirming, absence as unconfirming.
Backed by: BleepingComputer / Kaspersky May 2026, Permiso DetentionDodger, TruffleHog GitHub
TF-005 - Cryptomining-campaign IAM role profile (HIGH/CRITICAL) — strong heuristic / precursor
Detects IAM roles created within the last 48 hours that carry broad compute
managed policies (AmazonEC2FullAccess, PowerUserAccess, AdministratorAccess,
AmazonECS_FullAccess, AWSLambda_FullAccess). The Hacker News documents the
related role-creation pattern in the late-2025 campaign: the threat actor
"called CreateServiceLinkedRole and CreateRole to create IAM roles for
autoscaling groups and AWS Lambda" and attached AWSLambdaBasicExecutionRole
to the Lambda role. The same actor also created an IAM user with
AmazonSESFullAccess attached - which is why TF-005 escalates to CRITICAL
when the same fresh role also has SES sending permissions. TF-005
generalises the role-creation signal to broader managed policies than the
specific HN quote; legitimate emergency response can produce the same
fresh-role pattern.
Backed by: The Hacker News Dec 2025, Dark Reading
TF-006 - MMDSv1 still in use on EC2 / AgentCore (HIGH/CRITICAL) — misconfiguration-like (EC2) / strong heuristic (AgentCore)
Detects two related conditions. EC2 instances where HttpTokens != required
(IMDSv1 still callable) - the entry point for documented AWS breaches since
the Capital One SSRF incident in 2019. Datadog 2025 State of Cloud Security
reported only 50% of EC2 instances enforce IMDSv2.
Bedrock AgentCore agents on metadataVersion=v1 (CRITICAL). Per Unit 42's
April 2026 "Cracks in the Bedrock"
research, AWS made MMDSv2 the default for new AgentCore agents on 14 February
2026 specifically because the prior token-less metadata service allowed
SSRF-style credential extraction from inside the microVM. Agents created
before that date still report v1 unless explicitly upgraded.
(Unit 42 also documented a separate DNS-tunneling sandbox bypass in the same article - related but distinct from the metadata issue.)
Backed by: Datadog 2025 State of Cloud Security, Unit 42 sandbox bypass
TF-007 - whoAMI confusion CI/CD precondition (MEDIUM) — precursor
Detects IAM roles trusted by CI/CD identities (codebuild service principals,
GitHub OIDC, GitLab OIDC, Buildkite federation) that have a broad EC2 managed
policy attached - the precondition for the whoAMI confusion attack. The
actual fix lives in pipeline code (must pass --owners on DescribeImages),
not IAM. The role is just the precondition that makes the attack reachable.
Backed by: Datadog Security Labs whoAMI research
TF-008 - CloudTrail tampering precursor (HIGH/CRITICAL) — strong IR signal
Detects CloudTrail trails that have been STOPPED (CRITICAL - a trail that
exists but is not logging is an unambiguous blind-spot regardless of cause;
CloudTrail stop is a known post-credential-theft attacker action and AWS
Security Hub ships CloudTrail.1 and CloudTrail.4 controls precisely for
this) or have a populated LatestDeliveryError (HIGH - S3 destination
broken, evidence is being dropped).
Backed by: AWS Security Hub CloudTrail controls
TF-009 - Roles Anywhere external-CA trust anchor (HIGH/MEDIUM) — misconfiguration-like
Detects IAM Roles Anywhere trust anchors with sourceType=CERTIFICATE_BUNDLE
instead of AWS_ACM_PCA. Anyone able to issue a chain-valid cert from the
trusted CA can call rolesanywhere:CreateSession and exchange the cert for
AWS temporary credentials. HIGH when enabled, MEDIUM when disabled
(re-enabling without fix re-introduces the exposure). Note: a deliberately
configured external CA bundle for a tightly-scoped hybrid setup may be
legitimate; the finding is a prompt for review, not a confirmed exploit.
Backed by: fwd:cloudsec 2025 talks
TF-010 - DataZone over-grant (HIGH) — misconfiguration-like (overgrant)
Detects AmazonDataZoneFullAccess attached to non-admin principals. DataZone
bridges identity, Glue catalog, and S3 storage - the full-access managed
policy is the canonical onboarding shortcut that gets forgotten and becomes
a single-principal-compromise path to the entire data plane. This is a
governance signal (dangerous overpermission) rather than evidence of active
abuse.
Backed by: AWS DataZone IAM docs
Architecture
Each pattern lives in src/cloud_audit/providers/aws/threat_feed/<name>.py
and exposes:
```python PATTERN_ID = "TF-XXX-name" # e.g. "TF-003-quarantine-policy" CHECK_ID = "aws-tf-XXX" # e.g. "aws-tf-003" PATTERN_NAME = "..." PATTERN_SEVERITY = Severity.HIGH # base severity (may escalate) DOC_URL = "https://..."
def detect(provider: AWSProvider) -> CheckResult: ... ```
Patterns produce standard Finding objects so they integrate with all
existing reporting (JSON, SARIF, HTML, Markdown), with two additions:
Finding.threat_pattern_id- theTF-XXXidentifierFinding.references: list[str]- URLs to backing research (always at least one)
The new Category.THREAT enum value separates threat findings from regular
Category.SECURITY misconfiguration findings in reports.
Adding a new pattern
- Create
src/cloud_audit/providers/aws/threat_feed/<name>.pyfollowing the module conventions above - Register it in
_PATTERN_MODULESinproviders/aws/threat_feed/__init__.py - Add tests in
tests/aws/threat_feed/test_<name>.py(mock the relevant AWS client; we do not use moto for threat patterns because most AWS managed policies aren't pre-loaded in the moto catalog) - Update
THREAT_FEED_VERSIONand the changelog