Back to blog
AWSBest PracticesCloud SecurityIdentity & AccessOperations & Compliance

IAM Group Has No Members: Cleaning Up Empty AWS Groups

Empty AWS IAM groups hide forgotten privileges and clutter audits. Learn why they matter and how to fix and prevent them with CLI, console, and IaC steps.

TL;DR

This check flags IAM groups that contain zero users. Empty groups clutter your access model, hide forgotten permission grants, and make audits harder. Either assign the right users to the group or delete it.

An IAM group with no members is one of those findings that looks harmless at first glance. Nobody is using it, so where is the risk? The problem is that an empty group is rarely empty by design. It usually represents a leftover from a reorg, an offboarding that was half finished, or a permission set that someone built and then abandoned. Each of those scenarios leaves a gap in your access model that nobody is watching.

This post walks through what the account_emptygroups check looks for, why empty groups are worth cleaning up, and how to fix and prevent them with CLI commands, console steps, and infrastructure as code.


What this check detects

The IAM Group Has No Members check inspects every IAM group in your AWS account and flags any group that has zero users attached to it. It does not look at the policies attached to the group, only at membership. A group with three managed policies and no users still fails this check.

Note: IAM groups are purely a convenience for managing users. You attach policies to a group, then add users to the group so they inherit those policies. Groups cannot be assumed like roles, and you cannot attach a group to a service or an EC2 instance. If a group has no users, none of its policies are doing anything.

So a failing result is telling you one simple thing: this group exists, it may carry permissions, and nobody is inheriting them.


Why it matters

Empty groups are a governance smell rather than a direct exploit path. But they create real problems over time.

1. They hide forgotten privilege

An empty group often still has policies attached, sometimes very broad ones like AdministratorAccess. The group sits dormant until someone adds a user to it, perhaps without realizing how much access that grant carries. A new hire dropped into a stale admins-temp group inherits everything that was ever attached to it.

2. They distort audits and least-privilege reviews

When a security team reviews who has access to what, empty groups add noise. Reviewers have to trace every group, confirm it has no members, and decide whether it is safe. Multiply that across dozens of accounts and the effort adds up. Clean access models are faster and cheaper to audit.

3. They signal incomplete offboarding

If a group used to hold a team and now holds nobody, ask what happened to those users. Were they properly removed, or were their accounts deleted while their access elsewhere lingers? An empty group can be the visible edge of a messier offboarding problem.

Warning: Do not assume an empty group is safe to ignore just because no one is in it. The danger is in what happens the next time someone is added. Treat the empty group as a loaded permission set waiting for a member.


How to fix it

You have two reasonable paths: assign the correct users to the group, or delete it. Start by understanding what the group actually grants before you decide.

Step 1: Inspect the group

List the group and see who, if anyone, belongs to it:

aws iam get-group --group-name developers-legacy

Then check what policies it carries, both managed and inline:

# Attached managed policies
aws iam list-attached-group-policies --group-name developers-legacy

# Inline policies
aws iam list-group-policies --group-name developers-legacy

Read those policies carefully. If the group grants admin or write access to sensitive services, that strengthens the case for deleting it rather than leaving it around.

Step 2a: If the group is still needed, add users

If the group has a legitimate purpose and just lost its members, add the right users back:

aws iam add-user-to-group \
  --group-name developers-legacy \
  --user-name jordan.lee

Step 2b: If the group is obsolete, delete it

To delete a group you first have to detach all of its policies, because AWS will not delete a group that still has policies or members attached.

Danger: Deleting a group is irreversible. Confirm the group truly has no members and that no automation or IaC recreates it before you remove it. If another team relies on this group name, deleting it can break their next deployment.

Detach managed policies:

aws iam detach-group-policy \
  --group-name developers-legacy \
  --policy-arn arn:aws:iam::aws:policy/PowerUserAccess

Delete inline policies:

aws iam delete-group-policy \
  --group-name developers-legacy \
  --policy-name custom-s3-access

Then delete the group:

aws iam delete-group --group-name developers-legacy

Console steps

  1. Open the IAM console and go to User groups.
  2. Select the group flagged by the check.
  3. Open the Users tab to confirm it has no members.
  4. Review the Permissions tab to see what it grants.
  5. To remove it, choose Delete, type the group name to confirm, and submit.

Tip: Before deleting, export the group's policy attachments to a file. That way, if you discover later that the group was needed, you can recreate it exactly. aws iam list-attached-group-policies --group-name developers-legacy > group-backup.json


How to prevent it from happening again

Cleanup is a one-time fix. The real win is making sure stale groups never accumulate again.

Manage groups as code

When groups and memberships live in Terraform or CloudFormation, an empty group becomes visible in code review rather than hiding in the console. Here is a Terraform example that ties membership directly to the group definition:

resource "aws_iam_group" "developers" {
  name = "developers"
}

resource "aws_iam_group_membership" "developers" {
  name  = "developers-membership"
  group = aws_iam_group.developers.name
  users = [
    aws_iam_user.jordan.name,
    aws_iam_user.priya.name,
  ]
}

If the users list ever empties out, that change shows up in the plan and a reviewer can ask why the group should still exist.

Gate it in CI/CD with policy as code

You can fail a pipeline before an empty group ever reaches AWS. With Open Policy Agent and Conftest, a rule against a Terraform plan might look like this:

package iam

deny[msg] {
  group := input.resource_changes[_]
  group.type == "aws_iam_group"
  membership := input.resource_changes[_]
  membership.type == "aws_iam_group_membership"
  membership.change.after.group == group.change.after.name
  count(membership.change.after.users) == 0
  msg := sprintf("IAM group '%s' has no members", [group.change.after.name])
}

Run a scheduled audit

For groups created outside of IaC, a scheduled job that lists empty groups keeps the problem from creeping back:

for group in $(aws iam list-groups --query 'Groups[].GroupName' --output text); do
  members=$(aws iam get-group --group-name "$group" \
    --query 'Users' --output text)
  if [ -z "$members" ]; then
    echo "Empty group: $group"
  fi
done

Tip: Rather than wiring up your own cron jobs, let Lensix run this check continuously across every account and surface empty groups the moment they appear, alongside the policies each one still carries.


Best practices

  • Tie group lifecycles to teams. When a team is dissolved or merged, decommission its groups as part of the same process. Do not let the group outlive the team.
  • Prefer groups over per-user policies. Groups are the right place to manage shared permissions, so keep using them. The fix for an empty group is to clean it up, not to abandon groups entirely.
  • Apply least privilege to group policies. Even a populated group should grant only what its members need. An empty group with admin access is a worst case, but a populated one is not much better.
  • Review group membership during offboarding. When a user leaves, remove them from every group explicitly rather than just deleting the user, so you can spot groups that are about to go empty.
  • Document group purpose. Use tags or a naming convention that makes the intent of each group obvious, so reviewers can tell at a glance whether an empty group is a mistake or a planned placeholder.

Empty IAM groups are cheap to fix and easy to prevent. Clean them up, manage them as code, and put a guardrail in your pipeline so the next stale group never makes it past review.