Back to blog
AWSBest PracticesCloud SecurityIdentity & AccessOperations & Compliance

AWS Password Policy Allows Password Reuse: Risks and Fix

Learn why letting IAM users reuse old passwords is risky, and how to enforce password reuse prevention in AWS with CLI, Terraform, and policy-as-code.

TL;DR

This check flags AWS accounts where the IAM password policy lets users cycle back to old passwords. Without a password reuse restriction, a compromised credential can be quietly reinstated. Fix it by setting PasswordReusePrevention to at least 24 in the account password policy.

Password rotation only works if users cannot rotate straight back to the password they just changed. When an IAM password policy has no reuse prevention, a user forced to update their password can set it to the same one a few cycles later, or simply alternate between two favourites. That defeats the entire point of rotation and leaves stale, possibly leaked credentials valid for far longer than intended.

This Lensix check (account_passwordreuse) inspects your AWS account password policy and reports a finding when the policy does not prevent reuse of previous passwords.


What this check detects

AWS lets you define a single account-wide password policy that governs how IAM users (the ones who sign in with a username and password, not federated identities) create and update their console passwords. One of the optional settings is PasswordReusePrevention, which tells IAM how many of a user's previous passwords to remember and block.

The check returns a fail when:

  • No account password policy exists at all, or
  • A policy exists but PasswordReusePrevention is unset, or
  • The remembered-password count is set too low for your security baseline

Note: This setting only affects IAM users with console access. If your organisation logs in through AWS IAM Identity Center (formerly SSO) or an external IdP, password rules live in that identity source instead. It is still worth setting a strong account policy for any break-glass or service IAM users that remain.


Why it matters

Password reuse prevention is one of those controls that looks like compliance box-ticking until you trace through how credentials actually get compromised.

The reuse loop defeats rotation

Say your policy forces a password change every 90 days but does not remember old passwords. A user with a habit of using Summer2024! simply changes to Spring2024! at rotation, then back again next quarter. If Summer2024! was scraped from a phishing kit or a third-party breach a year ago, it is still live. The attacker waits for the predictable cycle and walks in.

Credential stuffing has a longer runway

Breach databases like the ones behind Have I Been Pwned contain billions of email and password pairs. Attackers replay those pairs against cloud consoles. If an IAM user reused a personal password and your policy lets that password stay valid indefinitely through reuse, you have handed an attacker a stable target.

Warning: IAM users with console access and no MFA are the highest-risk version of this problem. Reuse prevention reduces the blast radius, but it is not a substitute for MFA. Treat a failing reuse check as a signal to audit MFA coverage too.

Compliance frameworks expect it

CIS AWS Foundations Benchmark, PCI DSS, and most internal security baselines call for a minimum password history. The CIS benchmark recommends preventing reuse of at least the last 24 passwords. A failing check here will surface in audits and slow down certifications.


How to fix it

You set reuse prevention as part of the account password policy. There is one policy per account, so updating it affects all IAM users at once.

Warning: The update-account-password-policy call replaces the entire policy, not just the field you pass. Always include every setting you want to keep, or you will silently reset things like minimum length back to defaults.

Option 1: AWS CLI

First, read the current policy so you know what you are working with:

aws iam get-account-password-policy

Then apply a policy that includes reuse prevention along with your other requirements:

aws iam update-account-password-policy \
  --minimum-password-length 14 \
  --require-symbols \
  --require-numbers \
  --require-uppercase-characters \
  --require-lowercase-characters \
  --max-password-age 90 \
  --password-reuse-prevention 24 \
  --allow-users-to-change-password

The key flag is --password-reuse-prevention 24, which blocks reuse of the last 24 passwords. The maximum value AWS accepts is 24.

Option 2: AWS Console

  1. Open the IAM console.
  2. In the left navigation, choose Account settings.
  3. Under Password policy, choose Edit (or Set password policy if none exists).
  4. Enable Prevent password reuse and set Number of passwords to remember to 24.
  5. Confirm the rest of your settings, then choose Save changes.

Option 3: Terraform

If you manage IAM as code, define the policy once and let your pipeline enforce it:

resource "aws_iam_account_password_policy" "strict" {
  minimum_password_length        = 14
  require_lowercase_characters   = true
  require_uppercase_characters   = true
  require_numbers                = true
  require_symbols                = true
  max_password_age               = 90
  password_reuse_prevention      = 24
  allow_users_to_change_password = true
}

Apply it and confirm the drift is gone:

terraform apply
aws iam get-account-password-policy --query 'PasswordPolicy.PasswordReusePrevention'

The command should return 24.

Tip: Wrap the password policy in a reusable Terraform module and apply it across every account in your organisation. Pairing this with AWS Organizations means new accounts inherit the baseline from day one rather than starting with the empty default policy.


How to prevent it from happening again

Fixing one account is easy. Keeping every account compliant as your footprint grows is the real work. A few approaches scale better than manual checks.

Detect drift with AWS Config

AWS Config ships a managed rule, iam-password-policy, that continuously evaluates your account policy against parameters you set, including reuse prevention. Deploy it as an organisation-wide conformance pack so every account is watched.

{
  "RequireUppercaseCharacters": "true",
  "RequireLowercaseCharacters": "true",
  "RequireSymbols": "true",
  "RequireNumbers": "true",
  "MinimumPasswordLength": "14",
  "PasswordReusePrevention": "24",
  "MaxPasswordAge": "90"
}

Gate it in CI/CD

If your IAM policy lives in Terraform, add a policy-as-code check that fails the build when reuse prevention is missing or too low. Here is an Open Policy Agent (Rego) rule for a Terraform plan:

package terraform.iam

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_iam_account_password_policy"
  reuse := resource.change.after.password_reuse_prevention
  reuse < 24
  msg := sprintf("password_reuse_prevention must be >= 24, got %d", [reuse])
}

Run it in your pipeline before terraform apply so non-compliant changes never reach AWS.

Tip: Lensix runs this check continuously across your accounts, so you get an alert the moment a policy drifts or a new account joins without one. That covers the gap between scheduled audits when manual reviews tend to miss things.


Best practices

Reuse prevention is one piece of a healthy IAM password posture. Round it out with these:

  • Remember 24 passwords. Use the maximum AWS allows. There is no downside, and it satisfies CIS.
  • Set a minimum length of 14 or more. Length beats complexity. Combine it with required character classes.
  • Enforce MFA on every console user. Reuse prevention slows attackers down, MFA stops them. Treat both as non-negotiable.
  • Minimise IAM users entirely. Move human access to IAM Identity Center or federation so password policy applies to a tiny number of break-glass accounts rather than your whole team.
  • Set a sensible max password age. 90 days is a common baseline, but pair it with reuse prevention so rotation actually means something.
  • Audit regularly. Run a credential report (aws iam generate-credential-report) to spot users with old passwords or no MFA.

Danger: Before tightening max-password-age on a live account, confirm your break-glass user has a current, securely stored password and working MFA. Locking yourself out of the one account you use to recover the others is a bad day no one forgets.

Password reuse prevention costs nothing to enable and closes a quiet but real gap in your account's defences. Set it once, enforce it in code, and let continuous monitoring keep it that way.