Direct user policies
Check ID: aws-iam-010
AWS-IAM-010 is an AWS security check performed by cloud-audit, an open-source AWS security scanner. Checks if IAM users have policies attached directly instead of through groups. Direct policy attachments bypass group-based access control and make permission auditing difficult.
Why it matters
Direct policy attachments create a permission management nightmare at scale. When policies are attached to individual users instead of groups, answering the question 'who has access to what?' requires checking every user individually rather than reviewing group memberships. This makes access reviews, compliance audits, and incident response significantly slower. In the 2021 Twitch source code leak post-mortem, investigators noted that direct user policies made it difficult to determine the full scope of compromised access. Group-based access control enables the principle of least privilege at scale: when an employee changes roles, you move them between groups instead of manually adjusting individual policy attachments. AWS IAM Access Analyzer's policy generation feature works more effectively with group-based policies.
Common causes
Quick-fix permissions are attached directly to users during incident response or debugging and never moved to groups afterward. Terraform configurations that use aws_iam_user_policy_attachment instead of aws_iam_group_policy_attachment because it is simpler to write. Lack of IAM governance standards means each team creates permissions in whatever way is fastest, resulting in a mix of group and direct attachments.
Detection
Run cloud-audit to detect this issue:
pip install cloud-audit
cloud-audit scan -R The -R flag includes remediation details for every finding, including this one.
Remediation: AWS CLI
# Detach policies from user and attach to a group:
aws iam detach-user-policy --user-name USERNAME --policy-arn POLICY_ARN
# Then add user to appropriate group:
aws iam add-user-to-group --user-name USERNAME --group-name APPROPRIATE_GROUP Remediation: Terraform
# Use group membership instead of direct policy attachment:
resource "aws_iam_group_membership" "user" {
name = "user-membership"
users = ["username"]
group = aws_iam_group.developers.name
} Compliance mapping
This check maps to CIS 1.15 in the CIS AWS Foundations Benchmark. The CIS Benchmark provides prescriptive guidance for configuring security options for a subset of AWS services.
This check is part of cloud-audit - install with pip install cloud-audit
Related article
AWS Security Audit: 17 Issues in Every Account →