Cloud provider suspicious activity email: what to check and fix first
For customers who got a security warning from their cloud provider and need a calm, practical response. This runbook helps you confirm whether the alert is real, identify the most common causes, and take the right containment and cleanup steps without guessing.
TL;DR — If your cloud provider emails about suspicious activity, treat it as real until you prove otherwise. The most common causes are leaked API keys, a compromised user account without multi-factor authentication (MFA, a second sign-in check), or an exposed server being used for spam, crypto-mining, or scanning; start by confirming the alert in your provider dashboard, reviewing recent sign-ins and API activity, then rotate credentials and isolate any affected server. Reading time: ~6 min
The scenario
It is a normal Tuesday afternoon and you get an email with a subject like "Suspicious activity detected on your account" or "We detected unusual outbound traffic from one of your instances." At the same time, nobody on your team remembers making infrastructure changes, but your billing graph looks odd and one app server has started running hot. Your client is asking whether customer data is at risk, and you need to answer quickly without making things worse. You do not need to be a cloud engineer to handle the first hour well; you just need a safe order of checks.
Symptoms
- Email from your provider with wording such as:
We detected suspicious activity associated with your account.
- Or:
We detected unusual API activity from an access key associated with your account.
- Or:
We detected unusual outbound network traffic from a compute instance.
- Unexpected new resources in the dashboard: extra virtual machines, snapshots, storage buckets, firewall rules, or users.
- Billing spike or usage spike in CPU, network egress, email sending, or object storage requests.
- Login history shows sign-ins from unknown IP addresses, countries, devices, or times.
- Audit log entries for actions your team did not perform, such as:
CreateInstance
CreateAccessKey
PutBucketPolicy
AuthorizeSecurityGroupIngress
- Server metrics show high CPU or outbound traffic while app traffic is normal.
- Mail provider or app logs show spam-like behavior, for example:
550 5.7.1 Message rejected as spam
- Web server logs show scanning or abuse patterns:
POST /wp-login.php HTTP/1.1
GET /.env HTTP/1.1
GET /phpmyadmin HTTP/1.1
Likely causes
| Cause | How common | Quick check |
|---|---|---|
| Leaked API key or access token used from outside your team | Very common | Provider dashboard → Security/Audit logs → filter for "CreateAccessKey", "CreateInstance", or API calls from unknown IPs |
| Compromised user account without MFA | Very common | Provider dashboard → Users/Identity → Sign-in history |
| Exposed server being abused for spam, scanning, or crypto-mining | Common | Provider dashboard → Compute/Instances → open the alerted instance → check CPU and network graphs |
| Publicly exposed storage bucket or object store | Sometimes | Provider dashboard → Storage/Buckets → open bucket permissions/public access settings |
| Overly open firewall/security group allowing internet access to admin ports | Sometimes | Provider dashboard → Network/Firewall or Security Groups → inspect inbound rules for 0.0.0.0/0 on 22, 3389, 5432, 3306 |
| Malicious code or dependency deployed through your app pipeline | Less common | Deployment platform or CI dashboard → recent deploys/Actions → inspect latest changes and secrets usage |
Step-by-step diagnosis
-
Confirm the alert in the provider dashboard, not just email. Open your provider's dashboard and go to the security, notifications, or support area where alerts are listed.
- This is your problem if: the same alert appears there with a resource ID, user, IP, or access key.
- Jump to: Step 2.
- If you cannot find it: contact provider support from inside the dashboard before clicking links in the email.
-
Check recent sign-ins for unknown users, IPs, or locations. Go to your provider dashboard → Identity/Users → Sign-in history or Security activity.
- This is your problem if: you see successful logins you do not recognize, especially without MFA or from unusual countries/times.
- Jump to: Fixes → Compromised user account without MFA.
-
Check audit logs for API actions you did not perform. Go to provider dashboard → Audit logs / Activity logs / Event history and filter the last 7 days.
- Look for actions like:
CreateInstance
RunInstances
CreateAccessKey
PutUserPolicy
AuthorizeSecurityGroupIngress
CreateBucket
PutBucketAcl
- This is your problem if: the actor, IP, user agent, or time does not match your team.
- Jump to: Fixes → Leaked API key or access token used from outside your team.
- Check whether a server is currently being abused. Go to provider dashboard → Compute/Instances → open the instance named in the alert → Metrics.
- This is your problem if: CPU is pinned, network outbound is unusually high, or there are unexplained processes or connections.
- Jump to: Fixes → Exposed server being abused for spam, scanning, or crypto-mining.
- If you have shell access, confirm with:
top
ss -tulpn
ps aux --sort=-%cpu | head
-
Check storage permissions for public access. Go to provider dashboard → Storage/Buckets → select the bucket mentioned in the alert → Permissions/Public access.
- This is your problem if: the bucket or objects are public when they should be private, or a bucket policy grants broad anonymous access.
- Jump to: Fixes → Publicly exposed storage bucket or object store.
-
Check firewall rules for open admin ports. Go to provider dashboard → Network/Firewall or Security Groups.
- This is your problem if: inbound rules allow
0.0.0.0/0or::/0to ports like22(SSH),3389(RDP),5432(Postgres), or3306(MySQL). - Jump to: Fixes → Overly open firewall/security group allowing internet access to admin ports.
- This is your problem if: inbound rules allow
-
Review the last deployment and CI secrets usage. Open your CI/CD dashboard or deployment platform → latest run/deploy → logs and changed files.
- This is your problem if: a recent deploy introduced unknown packages, suspicious scripts, or printed secrets into logs.
- Jump to: Fixes → Malicious code or dependency deployed through your app pipeline.
View as text
[Alert Email] ---- 1. confirm in dashboard ----> [Provider Alert]
|
v
[Sign-in History] <---- 2. check users ---- [Identity]
|
v
[Audit Logs] <---- 3. check API calls ---- [Activity]
|
v
[Instance Metrics] ---- 4. isolate host ----> [Compute]
|
v
[Bucket Permissions] ---- 5. review ----> [Storage]
|
v
[Firewall Rules] ---- 6. lock down ----> [Network]Fixes
Leaked API key or access token used from outside your team
⚠️ Rotating a key can break deployments, backups, or apps that still use the old secret. Before deleting a key, update every system that depends on it.
- In your provider dashboard, go to Identity/API keys and find the key used in suspicious events.
- Create a replacement key if the app still needs one.
- Update the secret anywhere it is stored: app hosting dashboard secrets, CI variables, backup jobs, or local password manager entries.
- Disable the old key first; if nothing breaks, delete it.
- Remove any unauthorized resources created by that key.
If your app stores provider credentials in environment variables, replace them and redeploy:
# Example names only; use your platform's secret manager/UI first
export CLOUD_ACCESS_KEY_ID="new-key-id"
export CLOUD_SECRET_ACCESS_KEY="new-secret"
Verify it worked: audit logs stop showing API calls from the old key, and your app/deploy still works with the new one.
Compromised user account without MFA
- In your provider dashboard → Users/Identity, force a password reset for the affected user.
- Sign out all active sessions if your provider offers that option.
- Enable MFA for that user and, if possible, require MFA for all admin users.
- Review group memberships and remove any unexpected admin role or policy.
- If the account created new keys, rotate those too.
Verify it worked: sign-in history shows only expected logins after the reset, and the user now shows MFA enabled.
Exposed server being abused for spam, scanning, or crypto-mining
⚠️ Isolating a server can cause downtime. If this instance serves production traffic, move traffic away first if you have a load balancer or standby instance.
- In your provider dashboard → Compute/Instances → affected instance → Networking, remove the public IP if your platform allows it, or attach a firewall rule that blocks inbound internet traffic.
- Restrict outbound traffic if your provider firewall supports egress rules.
- If you have shell access, collect quick evidence, then stop suspicious processes:
top
ss -tulpn
ps aux --sort=-%cpu | head -20
sudo systemctl list-units --type=service --state=running
- Check for common persistence points:
crontab -l
sudo ls -la /etc/cron.d
sudo systemctl list-unit-files | grep enabled
- If the host is clearly compromised, rebuild it from a known-good image rather than trying to "clean" it in place.
- Rotate any secrets that were present on that server: app secrets, database passwords, SMTP credentials, and provider keys.
Verify it worked: CPU/network graphs return to normal and no new suspicious connections or processes appear.
Publicly exposed storage bucket or object store
- In your provider dashboard → Storage/Buckets → affected bucket → Permissions/Public access.
- Turn off public access unless the bucket is intentionally public.
- Remove broad anonymous policies such as read access for everyone.
- If sensitive files were exposed, rotate any credentials found in those files and review access logs.
A safe bucket policy pattern is "private by default". If your provider supports JSON policies, remove statements that grant Principal: * access unless explicitly required.
Verify it worked: opening an object URL in a private browser now returns access denied instead of the file.
Overly open firewall/security group allowing internet access to admin ports
- In your provider dashboard → Network/Firewall or Security Groups, edit inbound rules.
- Remove public access to admin ports. Keep only required web ports public:
Allow 80/tcp from 0.0.0.0/0 if needed
Allow 443/tcp from 0.0.0.0/0
Remove 22/tcp from 0.0.0.0/0
Remove 3389/tcp from 0.0.0.0/0
Remove 5432/tcp from 0.0.0.0/0
Remove 3306/tcp from 0.0.0.0/0
- Re-add admin access only from your office/VPN static IP or a bastion host (a locked-down jump server).
If you need a quick command from a Linux machine to see what is exposed from the server side:
ss -tulpn
Verify it worked: the firewall rule list no longer shows public admin ports, and external port scans no longer reach them.
Malicious code or dependency deployed through your app pipeline
- Open your CI/CD or deployment dashboard and inspect the latest successful runs.
- Revert the last suspicious deploy from the platform UI, or redeploy the last known-good commit.
- Rotate any secrets that appeared in logs or build output.
- Review dependency changes in your lockfile and remove anything unexpected.
If you use Git locally, compare the last two deploys:
git log --oneline -n 5
git diff HEAD~1..HEAD
Verify it worked: the reverted deployment runs normally, and no further suspicious actions appear in logs or provider alerts.
Prevention
- Require MFA for every admin user and remove shared logins. In your provider identity settings, enable an MFA-required policy for admin roles. Keep one emergency break-glass account stored offline.
- Stop using long-lived API keys where possible. Prefer short-lived tokens or workload identity from your hosting platform. If you must use keys, store them only in your platform's secret manager, not in
.envfiles committed to Git. - Alert on risky audit-log events. Create alerts for events such as new access keys, new admin users, firewall changes, public bucket policies, and instance creation outside business hours. Example event names to watch:
["CreateAccessKey","CreateUser","AttachUserPolicy","AuthorizeSecurityGroupIngress","PutBucketAcl","RunInstances"]
- Block public access to admin ports by default. Keep a baseline firewall template that only allows web traffic publicly:
443/tcp from 0.0.0.0/0
80/tcp from 0.0.0.0/0
22/tcp from VPN_IP/32 only
3389/tcp from VPN_IP/32 only
- Add secret scanning to CI before every merge. Use your Git host's secret scanning or a scanner in CI so leaked keys are caught before deploy. Example CI step:
gitleaks detect --source . --verbose
- Use immutable rebuilds for servers. Keep infrastructure definitions and app deploy scripts so you can replace a compromised server quickly instead of repairing it manually. Even a simple documented rebuild checklist is better than ad-hoc fixes.
This article was written by an AI system and published pending human review. Verify anything you intend to act on.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI