Your AWS Account Is Probably Misconfigured: The 10 Things We Fix First
We’ve audited dozens of AWS accounts across startups, mid-market companies, and enterprises. The pattern is remarkably consistent. About 80% of the security issues we find in the first week fall into the same ten categories. These aren’t exotic attack vectors. They’re basic misconfigurations that exist because someone set up the account in a hurry three years ago and nobody reviewed it since.
Here are the ten things we fix first, in roughly the order we tackle them.
1. The Root Account Has No MFA (or Someone Is Using It Daily)
This is the single most dangerous finding we encounter. The root account in AWS has unrestricted access to everything, including billing, account closure, and the ability to bypass every IAM policy you’ve written.
We still find root accounts with no MFA enabled. Worse, we find root accounts being used for daily operations because “it was easier.”
Fix it: Enable a hardware MFA device on root. YubiKeys work great. Store the recovery codes in a physical safe or a break-glass process. Then stop using root entirely. Create an IAM user or SSO role for admin tasks. The only time root should be used is for the handful of tasks that genuinely require it, like changing the account’s support plan or closing the account.
2. IAM Users with Long-Lived Access Keys
This is the most common credential exposure we see. Developers create IAM users with programmatic access keys, put them in .env files or config, and never rotate them. We’ve found access keys that were over four years old.
Long-lived credentials are the number one way AWS accounts get compromised in the real world. Someone commits a key to a public repo, or a laptop gets stolen, or a former employee’s key never gets deactivated.
Fix it: Migrate to IAM Identity Center (formerly AWS SSO) for human access. Use IAM roles with temporary credentials for applications. If you absolutely must use access keys, enforce rotation with an IAM policy and set up automated alerts for keys older than 90 days. Run aws iam generate-credential-report right now and check the access_key_1_last_rotated column.
3. Overly Permissive IAM Policies
We see "Effect": "Allow", "Action": "*", "Resource": "*" in production IAM policies far more often than anyone wants to admit. Sometimes it’s on a service role. Sometimes it’s on a developer’s IAM user. Either way, it means a single compromised credential gives an attacker full control of your account.
Almost as bad: policies that grant s3:* or ec2:* when the application only needs s3:GetObject on a single bucket.
Fix it: Start with AWS Access Analyzer. It can generate least-privilege policies based on actual CloudTrail activity. Run it against your existing roles and it will tell you exactly which permissions are being used. Then replace the broad policy with a scoped one. This is tedious work, but it’s the single highest-impact security improvement you can make.
4. S3 Buckets with Public Access or Broken Policies
The S3 Block Public Access setting exists at both the account level and the bucket level. We regularly find accounts where the account-level block is enabled but individual buckets have it disabled, or vice versa.
Beyond public access, we find bucket policies that grant access to "Principal": "*" with conditions that don’t actually restrict access the way the author intended. S3 bucket policy logic is not intuitive. The interaction between bucket policies, IAM policies, and ACLs creates a matrix that’s easy to get wrong.
Fix it: Enable S3 Block Public Access at the account level. Then audit every bucket that has it disabled at the bucket level and confirm there’s a legitimate reason (like a static website bucket fronted by CloudFront). Use aws s3api get-bucket-policy and get-bucket-acl to audit each bucket. If you need public content delivery, use CloudFront with an Origin Access Control, not a public bucket.
5. Security Groups Allow 0.0.0.0/0 on Non-Web Ports
Every account we audit has at least one security group that allows inbound traffic from 0.0.0.0/0 on port 22 (SSH) or 3389 (RDP). Sometimes it’s a “temporary” rule from two years ago. Sometimes it’s on a database port.
Fix it: Remove all 0.0.0.0/0 inbound rules except for ports 80 and 443 on load balancers or web servers. For SSH access, use AWS Systems Manager Session Manager instead. It provides shell access through the AWS API with full audit logging, no open ports required. If you must allow SSH, restrict it to specific IP ranges and put it behind a bastion host.
6. CloudTrail Is Not Enabled in All Regions (or at All)
CloudTrail is your audit log. Without it, you have no record of who did what in your account. We’ve found accounts where CloudTrail was enabled only in us-east-1 because that’s where the infrastructure lives. An attacker who spins up resources in eu-west-1 would leave no trace.
We’ve also found accounts where CloudTrail was enabled but the S3 bucket storing the logs had a lifecycle policy that deleted them after 30 days.
Fix it: Create an organization-level trail that covers all regions. Enable log file validation so you can detect tampering. Store logs in a dedicated security account’s S3 bucket with a lifecycle policy of at least one year. Enable CloudTrail Insights to detect unusual API activity. This costs very little and gives you the foundation for any future incident investigation.
7. No GuardDuty or Threat Detection
GuardDuty is AWS’s managed threat detection service. It analyzes CloudTrail, VPC Flow Logs, and DNS logs to detect compromised instances, reconnaissance, and credential abuse. It costs pennies per GB of logs analyzed. Yet we find it disabled in roughly half the accounts we audit.
Fix it: Enable GuardDuty in every region. Set up an SNS topic for high-severity findings and route them to whatever alerting system your team uses, whether that’s Slack, PagerDuty, or email. The signal-to-noise ratio out of the box is good. You won’t be drowning in false positives.
8. No Encryption at Rest on Data Stores
RDS instances, EBS volumes, S3 buckets, DynamoDB tables. We routinely find production data stores with no encryption at rest configured. This is often because the resources were created before encryption-by-default settings existed, or because someone used the console and skipped that checkbox.
Fix it: Enable default encryption on all S3 buckets using SSE-S3 or SSE-KMS. Enable default EBS encryption at the account level (this is a one-click setting per region). For existing RDS instances, you’ll need to create an encrypted snapshot and restore from it. Going forward, set AWS Config rules to flag any unencrypted resources.
9. No AWS Config or Compliance Monitoring
AWS Config continuously records your resource configurations and evaluates them against rules. Without it, configuration drift goes undetected. Someone opens a security group, nobody notices, and it stays open for months.
Fix it: Enable AWS Config in all regions. Deploy the AWS Config Conformance Pack for your compliance framework (CIS Benchmarks is a great starting point). Set up auto-remediation for high-risk findings like public S3 buckets and open security groups using Config Rules with SSM Automation documents. The CIS AWS Foundations Benchmark pack covers most of the items on this list.
10. No Account Separation or Organization Structure
The final pattern we see is everything running in a single AWS account. Production, staging, development, CI/CD, logging, and the company’s SaaS subscriptions all share one account. This means a developer testing in “staging” has implicit access to production data. A compromised CI/CD pipeline can reach everything.
Fix it: Set up AWS Organizations with separate accounts for production, staging, development, security (for centralized logging), and shared services. Use Service Control Policies to enforce guardrails across the organization. This is a bigger lift than the other items on this list, but it’s the architectural foundation that makes everything else manageable.
Where to Start
If you’re looking at this list and recognizing your own account, don’t panic. Start with items 1, 2, and 6: secure root, eliminate long-lived credentials, and turn on CloudTrail everywhere. Those three changes take less than a day and dramatically reduce your risk.
Then work through the rest over the next few weeks. If you want help prioritizing or need someone to do the hands-on work, that’s exactly what we do. We embed senior engineers with your team to fix these issues and build the processes that prevent them from coming back.
Need help with this?
We place senior security engineers with teams like yours. Tell us what you're working on.
Get in Touch