AWS security baseline check

Account Demo sandbox (deliberately misconfigured) (453348321107) · regions ap-southeast-2 · 08 Nov 2026, 17:20 UTC
Baseline score
12/100F
weighted by severity
Controls failing
16 of 25
5 critical · 2 high · 7 medium · 2 low
Controls passing
2
3 not applicable · 0 to review
Coverage
82%
of the baseline could be evaluated

Summary

The account was checked against 25 baseline controls covering identity, logging, data, network and secrets, using read-only access only. It scores 12/100 (grade F). The most urgent finding: Security group acme-demo-1107-legacy-admin (sg-0f589326b0d3de0db) has SSH port 22 open to the Internet (NC-01, critical). Open admin and database ports are scanned constantly; one weak password or unpatched service is enough. Nothing was changed in the account. Every fix below is code or a command for you to review and apply; a retest scan confirms it.

Top risks

SeverityControlWhat we foundFirst step
critical NC-01 No SSH, RDP or database port is open to the whole internet Security group acme-demo-1107-legacy-admin (sg-0f589326b0d3de0db) has SSH port 22 open to the Internet. (sg-0f589326b0d3de0db)
Security group acme-demo-1107-legacy-admin (sg-0f589326b0d3de0db) has Postgres port 5432 open to the Internet. (sg-0f589326b0d3de0db)
aws ec2 revoke-security-group-ingress --group-id <sg> --protocol tcp --port 22 --cidr 0.0.0.0/0
critical SP-01 No secrets in Lambda variables, EC2 user data or launch templates Potential secret found in Lambda function acme-demo-1107-invoice-mailer variables -> Generic Password in variable SMTP_PASSWORD, SMTP Credentials in variable SMTP_PASSWORD. (acme-demo-1107-invoice-mailer)
Potential secret found in EC2 instance i-011db38cbdb70e4dd User Data -> Generic Password on line 2. (i-011db38cbdb70e4dd)
Move each value to Secrets Manager or SSM Parameter Store (SecureString), read it at runtime, then rotate it - it must be treated as exposed.
critical DA-01 S3 Block Public Access is on for the whole account Block Public Access is not configured for the account 453348321107. (453348321107)
module.security_baseline: s3_account_public_access_block = true
critical DA-02 No bucket is public S3 Bucket acme-demo-453348321107-uploads has public access due to bucket policy. (acme-demo-453348321107-uploads)
aws s3api put-public-access-block --bucket <bucket> --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
critical LD-01 CloudTrail records every region, with tamper-evident, private logs No CloudTrail trails enabled with logging were found. (453348321107)
module.security_baseline: cloudtrail = true # multi-region trail, log-file validation, private encrypted bucket

All controls

Identity and access

Not evaluatedID-01 · Root user is protected (MFA on, no access keys)critical

The root user can do everything, including closing the account. A stolen root password or key is a total loss.

not evaluated (the scanner returned no result - see Method)
Prowler: iam_root_mfa_enabled, iam_no_root_access_key
PassID-02 · Every console user has MFAhigh

Passwords get phished and reused. MFA stops most account takeovers.

2 items checked, all passing
Prowler: iam_user_mfa_enabled_console_access · CIS-7.0 2.10
PassID-03 · Access keys are rotated and unused keys removedhigh

Long-lived keys leak through laptops, CI logs and git history. Datadog found active keys over a year old at 59% of IAM users.

8 items checked, all passing
Prowler: iam_rotate_access_key_90_days, iam_user_accesskey_unused, iam_user_console_access_unused · CIS-7.0 2.11, CIS-7.0 2.12
FailID-04 · People get permissions through groups, roles or SSO - not attached to usersmedium

Permissions attached user by user drift and are never reviewed. Groups, roles and IAM Identity Center keep access auditable.

2 failing items
Evidence (2)
ResourceRegionFinding
arn:aws:iam::453348321107:user/acme-demo-1107-ci-deployap-southeast-2User acme-demo-1107-ci-deploy has the inline policy deny-everything attached.
arn:aws:iam::453348321107:user/acme-demo-1107-legacy-adminap-southeast-2User acme-demo-1107-legacy-admin has the policy AdministratorAccess attached.
How to fix
aws iam detach-user-policy --user-name <user> --policy-arn <arn>   # after adding the user to a group with the same rights
Console: Prefer IAM Identity Center: one login per person, permission sets per job, no long-lived keys.
Prowler: iam_policy_attached_only_to_group_or_roles · CIS-7.0 2.13
FailID-05 · Full administrator rights are limited to a break-glass rolehigh

Every identity with AdministratorAccess is a way to lose the whole account. Most teams need two or three, not ten.

1 failing item, 11 passing
Evidence (1)
ResourceRegionFinding
arn:aws:iam::aws:policy/AdministratorAccessap-southeast-2AWS policy AdministratorAccess is attached and allows '*:*' administrative privileges.
How to fix
aws iam list-entities-for-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
Console: Replace AdministratorAccess with job-based policies (PowerUserAccess, ReadOnlyAccess, or service-scoped). Keep one MFA-protected break-glass role.
Prowler: iam_aws_attached_policy_no_administrative_privileges, iam_customer_attached_policy_no_administrative_privileges, iam_inline_policy_no_administrative_privileges · CIS-7.0 2.14
FailID-06 · Password policy requires long, non-reused passwordslow

Only matters for IAM users with console access, but auditors and customer questionnaires ask for it.

2 failing items
Evidence (2)
ResourceRegionFinding
arn:aws:iam:ap-southeast-2:453348321107:password-policyap-southeast-2IAM password policy does not require minimum length of 14 characters.
arn:aws:iam:ap-southeast-2:453348321107:password-policyap-southeast-2IAM password policy reuse prevention is less than 24 or not set.
How to fix
Terraform: module.security_baseline: iam_password_policy = true
aws iam update-account-password-policy --minimum-password-length 14 --password-reuse-prevention 24 --require-symbols --require-numbers --require-uppercase-characters --require-lowercase-characters
Prowler: iam_password_policy_minimum_length_14, iam_password_policy_reuse_24 · CIS-7.0 2.8, CIS-7.0 2.9
Not evaluatedID-07 · IAM Access Analyzer watches for external accessmedium

It flags buckets, roles and keys shared with other accounts or the public - for free.

not evaluated (the scanner returned no result - see Method)
Prowler: accessanalyzer_enabled

Logging and detection

FailLD-01 · CloudTrail records every region, with tamper-evident, private logscritical

Without CloudTrail there is no record of who did what - no investigation, and no basis for a breach report.

1 failing item
Evidence (1)
ResourceRegionFinding
arn:aws:cloudtrail:ap-southeast-2:453348321107:trailap-southeast-2No CloudTrail trails enabled with logging were found.
How to fix
Terraform: module.security_baseline: cloudtrail = true # multi-region trail, log-file validation, private encrypted bucket
aws cloudtrail create-trail --name org-trail --s3-bucket-name <bucket> --is-multi-region-trail --enable-log-file-validation
aws cloudtrail start-logging --name org-trail
Prowler: cloudtrail_multi_region_enabled, cloudtrail_log_file_validation_enabled, cloudtrail_logs_s3_bucket_is_not_publicly_accessible · CIS-7.0 4.1
Not evaluatedLD-02 · GuardDuty threat detection is onhigh

GuardDuty spots stolen credentials, crypto-mining and unusual API calls. Costs a few dollars a month for small accounts.

not evaluated (the scanner returned no result - see Method)
Prowler: guardduty_is_enabled
FailLD-03 · AWS Config records configuration changesmedium

Config keeps a history of how each resource was configured - the evidence auditors and investigators ask for.

1 failing item
Evidence (1)
ResourceRegionFinding
arn:aws:config:ap-southeast-2:453348321107:recorderap-southeast-2AWS Config recorder 453348321107 is disabled.
How to fix
Terraform: module.security_baseline: config_recorder = true
Console: AWS Config > Get started > record all resources > deliver to the CloudTrail logs bucket.
Prowler: config_recorder_all_regions_enabled · CIS-7.0 4.3
FailLD-04 · Log groups keep logs for at least a yearmedium

Logs kept for days or weeks are gone when an incident is found months later. One year is the minimum many customers - and India's DPDP Rules - expect for security logs. ('Never expire' passes here; the cost check LOGS-001 flags its price.)

1 failing item
Evidence (1)
ResourceRegionFinding
arn:aws:logs:ap-southeast-2:453348321107:log-group:/acme-demo-1107/api:*ap-southeast-2Log Group /acme-demo-1107/api has less than 365 days retention period (7 days).
How to fix
bash aws-foundation/fix-pack/scripts/set-log-retention.sh --days 365   # dry run first; add --apply to change
Prowler: cloudwatch_log_group_retention_policy_specific_days_enabled
FailLD-05 · Spend alerts would catch abuse within a daymedium

A stolen key used for crypto-mining shows up first on the bill. Budgets with email alerts are free.

1 failing item
Evidence (1)
ResourceRegionFinding
arn:aws:budgets::453348321107:budgetglobalNo budget with an alert: abuse of a stolen key would only show up on the monthly bill
How to fix
Terraform: module.security_baseline: monthly_budget_usd = <amount>, alert_emails = [...] (or aws-bill-doctor/terraform/budget-guard)
Native check: spend_alerts

Data protection

FailDA-01 · S3 Block Public Access is on for the whole accountcritical

One account-wide switch stops any bucket from being made public by mistake - the cause of many data leaks.

1 failing item
Evidence (1)
ResourceRegionFinding
arn:aws:s3:ap-southeast-2:453348321107:accountap-southeast-2Block Public Access is not configured for the account 453348321107.
How to fix
Terraform: module.security_baseline: s3_account_public_access_block = true
aws s3control put-public-access-block --account-id <account> --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
Prowler: s3_account_level_public_access_blocks · CIS-7.0 3.1.4
FailDA-02 · No bucket is publiccritical

Public buckets are found by automated scanners within hours.

1 failing item, 3 passing
Evidence (1)
ResourceRegionFinding
arn:aws:s3:::acme-demo-453348321107-uploadsap-southeast-2S3 Bucket acme-demo-453348321107-uploads has public access due to bucket policy.
How to fix
aws s3api put-public-access-block --bucket <bucket> --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
# if the bucket serves a website, put CloudFront with origin access control in front instead
Prowler: s3_bucket_public_access, s3_bucket_policy_public_write_access, s3_bucket_public_list_acl, s3_bucket_public_write_acl · CIS-7.0 2.21
FailDA-03 · Data is encrypted by default (S3 and EBS)medium

Default encryption is free and protects disks, snapshots and buckets that get copied or shared by mistake.

1 failing item, 1 passing
Evidence (1)
ResourceRegionFinding
arn:aws:ec2:ap-southeast-2:453348321107:volumeap-southeast-2EBS Default Encryption is not activated.
How to fix
Terraform: module.security_baseline: ebs_encryption_by_default = true
aws ec2 enable-ebs-encryption-by-default --region <region>
Prowler: s3_bucket_default_encryption, ec2_ebs_default_encryption · CIS-1.5 2.1.1, CIS-7.0 6.1.1
No resourcesDA-04 · Databases are encrypted, private, backed up and protected from deletionhigh

An RDS instance reachable from the internet, without backups, is one mistake away from a data leak or permanent loss.

no matching resources in the scanned regions
Prowler: rds_instance_storage_encrypted, rds_instance_no_public_access, rds_instance_backup_enabled, rds_instance_deletion_protection
No resourcesDA-05 · No snapshot is publiccritical

A public EBS or RDS snapshot hands a full copy of the disk or database to anyone.

no matching resources in the scanned regions
Prowler: ec2_ebs_public_snapshot, rds_snapshots_public_access

Network and compute

FailNC-01 · No SSH, RDP or database port is open to the whole internetcritical

Open admin and database ports are scanned constantly; one weak password or unpatched service is enough.

2 failing items, 3 passing
Evidence (2)
ResourceRegionFinding
arn:aws:ec2:ap-southeast-2:453348321107:security-group/sg-0f589326b0d3de0dbap-southeast-2Security group acme-demo-1107-legacy-admin (sg-0f589326b0d3de0db) has SSH port 22 open to the Internet.
arn:aws:ec2:ap-southeast-2:453348321107:security-group/sg-0f589326b0d3de0dbap-southeast-2Security group acme-demo-1107-legacy-admin (sg-0f589326b0d3de0db) has Postgres port 5432 open to the Internet.
How to fix
aws ec2 revoke-security-group-ingress --group-id <sg> --protocol tcp --port 22 --cidr 0.0.0.0/0
# use SSM Session Manager (no open port) or a VPN/allow-list instead
Prowler: ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22, ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389, ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306, ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432, ec2_securitygroup_allow_ingress_from_internet_to_all_ports · CIS-7.0 6.3, CIS-7.0 6.4
No resourcesNC-02 · Default security groups allow no trafficlow

Resources launched without a chosen group land in the default one; it should block everything.

no matching resources in the scanned regions
Prowler: ec2_securitygroup_default_restrict_traffic
FailNC-03 · Instances require IMDSv2high

IMDSv1 lets an SSRF bug in a web app read the instance's cloud credentials (the Capital One breach). Datadog found IMDSv2 enforced on only 49% of instances.

2 failing items
Evidence (2)
ResourceRegionFinding
arn:aws:ec2:ap-southeast-2:453348321107:accountap-southeast-2IMDSv2 is not enabled by default for EC2 instances.
arn:aws:ec2:ap-southeast-2:453348321107:instance/i-011db38cbdb70e4ddap-southeast-2EC2 Instance i-011db38cbdb70e4dd has IMDSv2 disabled or not required.
How to fix
Terraform: module.security_baseline: ec2_imdsv2_default = true # new instances
bash aws-foundation/fix-pack/scripts/require-imdsv2.sh --regions <region>   # dry run lists instances; --apply after testing one
aws ec2 modify-instance-metadata-options --instance-id <id> --http-tokens required --http-put-response-hop-limit 2
Prowler: ec2_instance_imdsv2_enabled, ec2_instance_account_imdsv2_enabled · CIS-2.0 5.6, CIS-7.0 6.7
FailNC-04 · Only intended instances have public IP addressesmedium

Every public instance is attack surface (and costs $3.65 a month per IPv4 address). Most belong behind a load balancer.

1 failing item
Evidence (1)
ResourceRegionFinding
arn:aws:ec2:ap-southeast-2:453348321107:instance/i-011db38cbdb70e4ddap-southeast-2EC2 Instance i-011db38cbdb70e4dd has a Public IP: 3.26.2.132 (ec2-3-26-2-132.ap-southeast-2.compute.amazonaws.com).
How to fix
Console: Move workloads to private subnets behind a load balancer; reach them with SSM Session Manager. Keep a public IP only where it is intended, and note it in the report.
Prowler: ec2_instance_public_ip

Secrets and pipelines

FailSP-01 · No secrets in Lambda variables, EC2 user data or launch templatescritical

Anyone with read-only access - including auditors and many SaaS tools - can read these fields.

2 failing items
Evidence (2)
ResourceRegionFinding
arn:aws:lambda:ap-southeast-2:453348321107:function:acme-demo-1107-invoice-mailerap-southeast-2Potential secret found in Lambda function acme-demo-1107-invoice-mailer variables -> Generic Password in variable SMTP_PASSWORD, SMTP Credentials in variable SMTP_PASSWORD.
arn:aws:ec2:ap-southeast-2:453348321107:instance/i-011db38cbdb70e4ddap-southeast-2Potential secret found in EC2 instance i-011db38cbdb70e4dd User Data -> Generic Password on line 2.
How to fix
Console: Move each value to Secrets Manager or SSM Parameter Store (SecureString), read it at runtime, then rotate it - it must be treated as exposed.
Prowler: awslambda_function_no_secrets_in_variables, ec2_instance_secrets_user_data, ec2_launch_template_no_secrets
FailSP-02 · Secrets Manager secrets rotate automaticallymedium

A secret that never changes stays valid after every leak.

1 failing item
Evidence (1)
ResourceRegionFinding
arn:aws:secretsmanager:ap-southeast-2:453348321107:secret:acme-demo-1107/db-z2qcofap-southeast-2SecretsManager secret acme-demo-1107/db has rotation disabled.
How to fix
aws secretsmanager rotate-secret --secret-id <id> --rotation-lambda-arn <arn> --rotation-rules AutomaticallyAfterDays=90
Prowler: secretsmanager_automatic_rotation_enabled
Not evaluatedSP-03 · CI/CD logs in with short-lived OIDC credentials, not stored keyshigh

Keys stored in CI were stolen in the tj-actions, Trivy and Checkmarx incidents. OIDC tokens expire in minutes.

not evaluated (the scanner returned no result - see Method)
Native check: ci_oidc
FailSP-04 · Container images are scanned on push and tags are immutablelow

Scanning catches known vulnerabilities before deployment; immutable tags stop a pushed image being silently replaced.

3 failing items
Evidence (3)
ResourceRegionFinding
arn:aws:ecr:ap-southeast-2:453348321107:registry/453348321107ap-southeast-2ECR registry 453348321107 has BASIC scanning without automated scanning enabled.
arn:aws:ecr:ap-southeast-2:453348321107:repository/acme-demo-1107/apiap-southeast-2ECR repository acme-demo-1107/api has scan on push disabled.
arn:aws:ecr:ap-southeast-2:453348321107:repository/acme-demo-1107/apiap-southeast-2Repository acme-demo-1107/api does not have immutability configured.
How to fix
Terraform: module.security_baseline: ecr_scan_on_push = true
aws ecr put-image-tag-mutability --repository-name <repo> --image-tag-mutability IMMUTABLE
Prowler: ecr_registry_scan_images_on_push_enabled, ecr_repositories_scan_images_on_push_enabled, ecr_repositories_tag_immutability

Checks that could not run

Method and limits