Back to Intelligence

9,000+ Active AWS Keys Exposed Publicly: Detection, Rotation, and Secrets Hygiene Guide for Defenders

SA
Security Arsenal Team
August 24, 2026
11 min read

Truffle Security's latest research should be a forcing function for every cloud security team: researchers identified more than 9,000 publicly accessible AWS access key pairs that were still active at the time of discovery. These weren't orphaned test credentials from sandbox accounts. They were functioning long-lived IAM keys — sitting in public code repositories, exposed configuration files, publicly indexed artifacts, and developer content — ready for anyone to pick up and use.

If you've been in IR long enough, you know how this story ends. I've worked multiple engagements where the initial access vector was an AWS key committed to a public GitHub repo months earlier. By the time the client noticed, the threat actor had enumerated the account, spun up GPU instances for cryptomining, staged data from S3, and in one case established persistence with newly created access keys on existing IAM users. The mean time between a key hitting a public repo and automated abuse is measured in minutes, not days — credential-harvesting bots crawl GitHub, GitLab, Pastebin, and public S3 buckets continuously.

This post breaks down what the Truffle Security findings mean for your environment, how to detect leaked-key abuse in CloudTrail, how to hunt for exposed keys on your endpoints and in your code, and how to eliminate the root cause: long-lived static credentials.

Technical Analysis

What Was Found

Truffle Security — the team behind the open-source TruffleHog secret-scanning tool — scanned public sources and validated discovered AWS credentials against the AWS API. The critical detail: these weren't just exposed secrets, they were verified live keys. Validation matters because a huge percentage of committed keys are revoked quickly or were dummy values. Over 9,000 that still authenticate represents real, exploitable attack surface across thousands of organizations.

AWS access key pairs consist of an Access Key ID (long-lived user keys begin with the AKIA prefix; temporary/session credentials typically begin with ASIA) and a 40-character secret access key. Anyone holding both can authenticate to the AWS API with whatever permissions the associated IAM principal has — and in far too many environments, those permissions are wildly over-scoped.

How Keys End Up Public

The exposure vectors seen in this research and in real IR casework are consistent:

  • Hardcoded credentials committed to public repositories — including keys buried in git history after the file was "deleted" (deletion does not remove history)
  • Configuration files, CI/CD pipeline definitions, and .env files published by mistake
  • Build artifacts, container images, and AMIs containing baked-in credentials
  • Publicly exposed S3 buckets and web roots hosting backup files, credentials files, or application configs
  • Developer content — blog posts, screenshots, Stack Overflow questions, documentation

The Attack Chain (Defender's View)

Once an attacker holds a live key pair, the typical progression is:

  1. Validation: sts:GetCallerIdentity to confirm the key works and identify the account — this is the single most common first API call after key theft
  2. Enumeration: iam:ListUsers, iam:ListRoles, iam:GetAccountAuthorizationDetails, s3:ListAllMyBuckets, ec2:DescribeInstances to map permissions and assets
  3. Privilege escalation / persistence: iam:CreateAccessKey on other users, iam:CreateLoginProfile, iam:AttachUserPolicy (often attaching AdministratorAccess)
  4. Objective execution: S3 data exfiltration, EC2/Lightsail instance creation for cryptomining or staging, SES abuse for phishing, Secrets Manager retrieval, and in destructive cases ransomware-style deletion with ransom notes left in buckets

Exploitation Status

This is confirmed, ongoing, in-the-wild abuse — not theoretical. Credential-scanning bots operate at internet scale, and canary-token testing by multiple researchers has repeatedly shown leaked AWS keys being probed within minutes of public exposure. There is no CVE associated with this story because it is not a software flaw; it is an operational security failure pattern. No CISA KEV entry applies, but the technique maps to MITRE ATT&CK T1552.001 (Credentials in Files), T1078.004 (Valid Accounts: Cloud Accounts), and T1136.003 (Create Account: Cloud Account) for the persistence phase.

Detection & Response

The highest-fidelity detection strategy for leaked-key abuse combines three layers: (1) CloudTrail behavioral analytics for API calls that don't match your legitimate usage patterns, (2) proactive hunting for keys stored on endpoints and in code, and (3) hard auditing of key age and usage via the IAM credential report. Below are field-tested detection content and hunt queries.

SIGMA Rules

These rules target the attack chain phases above. Rule 1 fires on validation/enumeration activity from the AWS CLI; tune the known-source-IP filter to your environment. Rule 2 catches persistence via new credential creation — in mature environments, CreateAccessKey should be rare and change-controlled. Rule 3 catches root account API usage, which should essentially never happen.

YAML
---
title: AWS STS GetCallerIdentity From AWS CLI - Possible Leaked Key Validation
id: 3c9f2a71-8b4d-4e56-a123-9f0e1d2c3b4a
status: experimental
description: Detects sts:GetCallerIdentity calls made via the AWS CLI, the canonical first API call an attacker makes to validate a leaked or stolen AWS access key. Correlate source IP and user agent against expected automation; high volume from unknown networks or unexpected IAM users indicates leaked-key abuse.
references:
  - https://attack.mitre.org/techniques/t1078/004/
  - https://www.infosecurity-magazine.com/news/researchers-thousands-eaked-aws/
author: Security Arsenal
date: 2026/03/10
tags:
  - attack.discovery
  - attack.t1078.004
logsource:
  product: aws
  service: cloudtrail
detection:
  selection:
    eventSource: 'sts.amazonaws.com'
    eventName: 'GetCallerIdentity'
    userAgent|contains: 'aws-cli'
  filter_known_automation:
    userIdentity.arn|contains:
      - ':assumed-role/'
  condition: selection and not filter_known_automation
falsepositives:
  - Developers and engineers validating credentials locally
  - Onboarding of new tooling; baseline CLI usage per IAM user and alert on anomalies
level: medium
---
title: AWS IAM Credential Persistence - Access Key or Login Profile Created
id: 7d2e5b18-4f3a-4c89-b456-2e7a9c1d5f60
status: experimental
description: Detects creation of new IAM access keys, login profiles, or inline/admin policy attachment. Attackers using leaked keys frequently create additional credentials on existing users for persistence. These events should be rare and tied to change tickets.
references:
  - https://attack.mitre.org/techniques/t1136/003/
  - https://attack.mitre.org/techniques/t1098/
author: Security Arsenal
date: 2026/03/10
tags:
  - attack.persistence
  - attack.t1136.003
  - attack.t1098
logsource:
  product: aws
  service: cloudtrail
detection:
  selection:
    eventSource: 'iam.amazonaws.com'
    eventName:
      - 'CreateAccessKey'
      - 'CreateLoginProfile'
      - 'UpdateLoginProfile'
      - 'AttachUserPolicy'
      - 'PutUserPolicy'
  condition: selection
falsepositives:
  - Legitimate IAM administration; alert volume should be low in mature environments
  - Approved onboarding workflows - allowlist specific admin principals
level: high
---
title: AWS Root Account API Activity
id: 1b6a4c93-2d8e-4f17-a789-5c3d8e2b9a41
status: test
description: Detects any successful API activity performed by the AWS root account. Root should have no access keys and should only authenticate interactively for a small set of account-management tasks. Any programmatic root activity is a critical finding, often indicating compromised root credentials.
references:
  - https://attack.mitre.org/techniques/t1078/004/
author: Security Arsenal
date: 2026/03/10
tags:
  - attack.initial_access
  - attack.t1078.004
logsource:
  product: aws
  service: cloudtrail
detection:
  selection:
    userIdentity.type: 'Root'
    eventType: 'AwsApiCall'
  condition: selection
falsepositives:
  - Rare legitimate root account tasks (e.g., changing account settings) - verify each occurrence manually
level: critical

KQL — Microsoft Sentinel Hunt

Sentinel ingests CloudTrail via the native AWS connector into the AWSCloudTrail table. This hunt surfaces the leaked-key abuse pattern: IAM user activity from source IPs that have never (or not recently) been seen for that principal, combined with enumeration and persistence API calls. Run it over 14 days against a 30-day baseline.

KQL — Microsoft Sentinel / Defender
// Hunt for IAM user API activity from previously unseen source IPs,
// focused on validation, enumeration, and persistence calls typical of leaked-key abuse
let baseline = AWSCloudTrail
| where TimeGenerated between (ago(30d) .. ago(14d))
| where UserIdentityType == "IAMUser"
| summarize by UserIdentityArn, SourceIpAddress;
AWSCloudTrail
| where TimeGenerated > ago(14d)
| where UserIdentityType in ("IAMUser", "Root")
| where EventName in~ ("GetCallerIdentity", "ListUsers", "ListRoles", "GetAccountAuthorizationDetails", "ListAccessKeys", "CreateAccessKey", "CreateLoginProfile", "AttachUserPolicy", "PutUserPolicy", "ListAllMyBuckets", "GetSecretValue", "CreateInstance", "RunInstances")
| where UserIdentityType == "Root"
    or (UserIdentityArn !in (baseline | project UserIdentityArn)
        or SourceIpAddress !in (baseline | project SourceIpAddress))
| summarize FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), ApiCalls = make_set(EventName), CallCount = count()
    by UserIdentityArn, UserIdentityType, SourceIpAddress, UserAgent, AwsRegion, RecipientAccountId
| sort by CallCount desc

Tune the baseline window to your environment and exclude known NAT egress ranges if your corporate traffic consolidates to stable IPs. Any Root row here is an immediate incident.

Velociraptor VQL — Endpoint Hunt for Stored AWS Credentials

Long-lived keys persist on developer workstations and build servers in ~/.aws/credentials, shell history, and stray config files. This artifact hunts for AWS key material on disk using the AKIA/ASIA prefix pattern — valuable both for proactive hygiene and for scoping exposure during an IR engagement.

VQL — Velociraptor
-- Hunt for AWS access key material stored in common credential locations on endpoints
SELECT FullPath, Size, Mtime,
       read_file(filename=FullPath, length=4096) AS ContentSnippet
FROM glob(globs=[
    'C:/Users/*/.aws/credentials',
    'C:/Users/*/.aws/config',
    '/home/*/.aws/credentials',
    '/home/*/.aws/config',
    '/root/.aws/credentials',
    '/Users/*/.aws/credentials'
])
WHERE ContentSnippet =~ 'AKIA[0-9A-Z]{16}'
   OR ContentSnippet =~ 'aws_secret_access_key'

Extend with a second glob pass over repo roots (**/.env, **/config/*.yml) if your IR scoping requires it, but keep the regex tight — the AKIA[0-9A-Z]{16} pattern is high-fidelity and won't flood you with noise.

Remediation / Audit Script

This Bash script uses the AWS CLI to enumerate all IAM users and their access keys, flags keys older than 90 days or keys unused for 90+ days, and optionally deactivates them. Run it in audit mode first, review output, then re-run with deactivation enabled.

Bash / Shell
#!/bin/bash
# aws-key-audit.sh - Audit and optionally deactivate stale/unused IAM access keys
# Usage: ./aws-key-audit.sh audit   (report only)
#        ./aws-key-audit.sh enforce (deactivate stale keys)

MODE="${1:-audit}"
MAX_AGE_DAYS=90
NOW=$(date +%s)

echo "user,key_id,status,created,age_days,last_used,action"

for USER in $(aws iam list-users --query 'Users[*].UserName' --output text); do
  for KEY in $(aws iam list-access-keys --user-name "$USER" \
      --query 'AccessKeyMetadata[*].AccessKeyId' --output text); do

    META=$(aws iam list-access-keys --user-name "$USER" --output json)
    CREATED=$(echo "$META" | jq -r ".AccessKeyMetadata[] | select(.AccessKeyId==\"$KEY\") | .CreateDate")
    STATUS=$(echo "$META" | jq -r ".AccessKeyMetadata[] | select(.AccessKeyId==\"$KEY\") | .Status")
    CREATED_EPOCH=$(date -d "$CREATED" +%s 2>/dev/null || date -j -f "%Y-%m-%dT%H:%M:%S" "${CREATED%%+*}" +%s)
    AGE_DAYS=$(( (NOW - CREATED_EPOCH) / 86400 ))

    LAST_USED=$(aws iam get-access-key-last-used --access-key-id "$KEY" \
      --query 'AccessKeyLastUsed.LastUsedDate' --output text 2>/dev/null)
    [ "$LAST_USED" = "None" ] && LAST_USED="never"

    ACTION="none"
    if [ "$AGE_DAYS" -gt "$MAX_AGE_DAYS" ] || [ "$LAST_USED" = "never" ]; then
      if [ "$MODE" = "enforce" ] && [ "$STATUS" = "Active" ]; then
        aws iam update-access-key --user-name "$USER" --access-key-id "$KEY" --status Inactive
        ACTION="DEACTIVATED"
      else
        ACTION="flagged_stale"
      fi
    fi

    echo "$USER,$KEY,$STATUS,$CREATED,$AGE_DAYS,$LAST_USED,$ACTION"
  done
done

# Also verify: root account must have ZERO access keys
aws iam get-account-summary --query 'SummaryMap.AccountAccessKeysPresent'
# Expected output: 0 - if 1, delete root keys immediately:
# aws iam delete-access-key --access-key-id <KEY_ID>   (run as root via console)

Remediation

Treat any confirmed public key exposure as an incident, not a hygiene task. Prioritized actions:

Immediate (hours):

  1. Deactivate, don't just rotate. For every exposed key: aws iam update-access-key --status Inactive first, validate nothing breaks, then delete. Rotating a key that an attacker already holds doesn't help if they created parallel credentials — check ListAccessKeys for every IAM user in the account for keys you don't recognize.
  2. Audit CloudTrail for the key's full lifetime of exposure. Look specifically for GetCallerIdentity from unknown IPs, new access key creation, AttachUserPolicy, S3 GetObject volume anomalies, and EC2 RunInstances in regions you don't use.
  3. Check for root access keys. Account summary must show zero. If root keys existed and were exposed, rotate root credentials, enforce MFA, and review all account-level settings.
  4. Review CloudWatch billing and Cost Explorer. Cryptomining abuse shows up as EC2/Lightsail spend in unfamiliar regions — often the first visible symptom.

Short-term (days):

  1. Generate and act on the IAM credential report (aws iam generate-credential-report) across every account in your Organization. Target: no key older than 90 days, no unused active keys, no keys on human users where federation is available.
  2. Scan everything with TruffleHog or Gitleaks — all repos including full git history, CI/CD artifacts, container images, and Slack/wiki exports. AWS's own git-secrets hooks and GitHub Push Protection (which AWS partners with) should be enabled org-wide; GitHub will now proactively notify AWS about leaked keys, and AWS will often apply a quarantine policy (AWSCompromisedKeyQuarantine_v2/v3) — check for it.
  3. Purge keys from git history (BFG Repo-Cleaner or git filter-repo). Remember: the key is already compromised; history cleanup prevents re-discovery but does not substitute for revocation.

Structural (the actual fix):

  1. Eliminate long-lived IAM user keys. Move humans to IAM Identity Center with short-lived federation; move workloads to IAM roles, instance profiles, RolesAnywhere, or OIDC-based CI/CD federation (GitHub Actions configure-aws-credentials with OIDC — no stored secrets at all). Temporary ASIA credentials expire in hours and drastically shrink the blast radius.
  2. Apply SCPs at the AWS Organizations level to deny IAM user key creation where feasible, restrict API calls to known IP ranges (aws:SourceIp condition) for sensitive roles, and block unused regions.
  3. Enable GuardDuty in all regions — it natively detects UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration, anomalous API calls, and known-bad source IPs. Pair it with IAM Access Analyzer for external-access findings and unused-access analysis.

Reference: Truffle Security research via Infosecurity Magazine, AWS IAM Best Practices, AWS compromised-key response runbook.

Related Resources

Security Arsenal Alert Triage Automation AlertMonitor Platform Book a SOC Assessment platform Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.