Skip to content

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 - the TF-XXX identifier
  • Finding.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

  1. Create src/cloud_audit/providers/aws/threat_feed/<name>.py following the module conventions above
  2. Register it in _PATTERN_MODULES in providers/aws/threat_feed/__init__.py
  3. 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)
  4. Update THREAT_FEED_VERSION and the changelog