AWS

Security

Outdated Default AWS IAM Policy Language Versions

Overview

The AWS Identity and Access Management (IAM) service is used to securely control access to AWS resources and can be expressed in JSON as IAM policies. The Version element of the JSON policy specifies which language syntax rules are used when processing the policy.

There are 2 possible Version element values: 2012-10-17 and 2008-10-17. The 2008-10-17 version is an earlier version that does not support newer features such as policy variables and AWS recommends not to use this version for any new policies or when updating existing policies. After going through all services that support IAM resource-based policies and identity-based policies, we found multiple AWS services that used the legacy 2008-10-17 policy version, including Gateway VPC Endpoint Policies, SNS Topic Policies, and SQS Queue Policies.

We sent details on our research and our thoughts regarding developer experience on outdated policy versions and default behavior to the AWS Security team on February 8th, 2023. This came up as a discussion point in an AWS Security online community regarding SNS Topic policies and we did further research on other default and example policies across all AWS services.

In this post, we will cover the IAM Policy Language Version and what that means, our research on which services have default legacy versions, the user experience in AWS when specifying the policy version, how to find default legacy versions in your AWS environment, and recommendations.

IAM Policy Language Version

A lesser known detail about IAM policy grammar is the policy Version element. This is not the different versions of IAM policies that can be created for managed policies via CreatePolicyVersion. We're referring to the snippet of "Version": "2008-10-17" or "Version": "2012-10-17" that may be included in an IAM policy. This Version specifies which language syntax rules are used when processing the IAM policy.

In AWS console and even in the CLI/API, there are default and example policies that leverage the legacy interpretation of the IAM policy language which can create issues for developers. IAM is one of the building blocks in AWS and often can be a source of headaches for developers to properly configure permissions and access for applications, let alone focus on least privilege and properly defined IAM permissions. By using the legacy 2008-10-17 version of the policy language, this can lead to misconfiguration and development time spent troubleshooting differences in language syntax rules such as policy variables being treated as literal strings in the policy.

There are 3 different implicit and explicit settings for the Version element:

  • Explicit 2012-10-17
  • Explicit 2008-10-17
  • Implicit 2008-10-17: No Version specified.

The Version element can be present in both identity-based policies and resource-based policies among other policy types.

  "Version": "2008-10-17",
"Id": "OutdatedVersionElement",
"Statement": [
{
"Sid": "ExampleStatement",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SQS:ReceiveMessage"]
}
...

Identity-Based Policies and Their Versions

There are 4 types of identity-based policies that we will take a look at:

AWS has controls that block the creation of IAM managed policies with legacy policy versions. The following screenshots show the mechanisms for blocking a policy created without 2012-10-17 specified in the policy version. In console, an error message pops up about the version string.

AWS Console Message for Policy Version

With the AWS CLI, we get a `MalformedPolicyDocument`` error:

AWS CLI Error for Policy Version

However, these controls are inconsistent and do not apply to inline policies. Inline policies still can be created with legacy policy versions of 2008-10-17 or with no Version specified.

We used the following JSON as our policy:

{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "ListPolicies",
"Effect": "Allow",
"Action": ["iam:ListPolicies"],
"Resource": "*"
}
]
}

The following command to put an inline policy on our cloudquery-user user succeeded:

aws iam put-user-policy \
--user-name cloudquery-user \
--policy-name test-cq-policy \
--policy-document file://2008policyversion.json

Finding Identity-Based Policies with CloudQuery

The below queries have a prerequisite to use CloudQuery to sync AWS data to PostgreSQL. For a guide, see our quickstart guide.

We will use CloudQuery to check for identity-based with 2008-10-17 explicitly set as the version or for identity-based policies without an explicit version set.

Finding IAM User Inline Policies

SELECT * FROM
(
SELECT policy_document ->> 'Version' as version, *
FROM aws_iam_user_policies
) as user_policies
WHERE version = '2008-10-17'
OR version is NULL;

Finding IAM Group Inline Policies

SELECT * FROM
(
SELECT policy_document ->> 'Version' as version, *
FROM aws_iam_group_policies
) as group_policies
WHERE version = '2008-10-17'
OR version is NULL;

Finding IAM Role Inline Policies

SELECT * FROM
(
SELECT policy_document ->> 'Version' as version, *
FROM aws_iam_role_policies
) as role_policies
WHERE version = '2008-10-17'
OR version is NULL;

Resource-Based Policies and Their Versions

In our research, we found 3 types of resource-based policies with default versions set to 2008-10-17:

The below table shows the AWS services we tested based on AWS Services that work with IAM. From our research, we found some services default to 2012-10-17, some services default to 2008-10-17, some services default to empty policies (Empty), and some services did not support writing full IAM policy JSON.

AWS ServiceDefault Policy Version ElementComments
AWS SQS2008Both Console and API/CLI
AWS SNS2008Both Console and API/CLI
AWS VPC Endpoints2008Gateway Endpoints Only
AWS VPC Endpoints2012Interface Endpoints (Did not test all Interface Endpoints)
AWS Lambda2012Console
AWS SES2012Console
AWS GlueEmptyConsole
AWS EFSEmptyConsole
AWS KMS2012Console
AWS Secrets Manager2012Console
AWS ECR (Repository)2012Console
AWS CloudWatch Logs2012API/CLI Only
AWS S32012Console
AWS IAM2012Console
AWS Private CAUnknownAPI/CLI Only
AWS API Gateway2012Console
AWS Cloud9NADoes not support full IAM Policy Language
AWS SAMNADoes not support full IAM Policy Language
AWS Backup2012Console
AWS S3 GlacierEmptyConsole
AWS S3 OutpostsUnknownDid Not Test
AWS CodeArtifact2012Console
AWS Lex v2EmptyConsole
AWS OpenSearch2012Console
AWS EventBridge Schemas2012Console
AWS EventBridge Event Buses2012Console
AWS Elemental MediaStore2012Console
AWS CloudTrail2012Console

Finding Resource-Based Policies with CloudQuery

We will use CloudQuery to check for resource-based policies with 2008-10-17 explicitly set as the version or for resource-based policies without an explicit version set. The following queries will be used to check for SQS queue policies, SNS topic policies, and VPC Endpoint policies. Additional queries can be written for other AWS resource-based policies.

Finding SQS Queues and Their Resource-Based Policies

SELECT * FROM
(
SELECT policy ->> 'Version' as version, *
FROM aws_sqs_queues
) as sqs_queues
WHERE version = '2008-10-17'
OR version is NULL;

Finding SNS Topics and Their Resource-Based Policies

SELECT * FROM
(
SELECT policy ->> 'Version' as version, *
FROM aws_sns_topics
) as sns_topics
WHERE version = '2008-10-17'
OR version is NULL;

Finding VPC Endpoints and Their Resource-Based Policies

SELECT * FROM
(
SELECT policy_document ->> 'Version' as version, *
FROM aws_vpc_endpoints
) as vpc_endpoints
WHERE version = '2008-10-17'
OR version is NULL;

Conclusion

The legacy policy version 2008-10-17 can be problematic for developers and application teams given the difference in interpretation by AWS.

We would like to see the following from AWS:

  • Example and default policies should have default policy versions set to 2012-10-17.
  • Not specifying a policy version should also default to 2012-10-17 once enough warning has been given to AWS customers.
  • In the interim, more controls similar to the IAM Managed Policy creation experience that block creation of new policies without 2012-10-17 specified.

In the interim, we have the following recommendations for AWS end users:

  • Scan AWS environments for any legacy usage of the 2008-10-17 policy language version.
  • If possible, update legacy policies to use the 2012-10-17 policy language version.
  • Ensure all new policies leverage the newer 2012-10-17 policy language version.

Stay tuned for more use cases we can build with CloudQuery on top of the infrastructure data we loaded from AWS!

Summary

Want to see CloudQuery in action? Schedule a demo with our team or check out the platform documentation to learn more.

Want help getting started? Join the CloudQuery community to connect with other users and experts, or message our team directly here if you have any questions.

References and Useful Links

CloudQuery: AWS integration

AWS: IAM JSON policy elements: Version

AWS: Grammar of the IAM JSON Policy Language

AWS: AWS Services that work with IAM

AWS: IAM Policy elements: Variables and Tags

Try CloudQuery yourself

Self-hosted, open source, and free to start. Or schedule a demo to see the managed version.

Related posts

AWS

Azure

GCP

Security

How Do You Run CloudQuery Without Static Credentials?

Workload identity federation for GCP and Azure, RDS IAM auth, and Lakebase OAuth let self-hosted CloudQuery syncs run without stored static credentials.

Ben Bernays

Ben Bernays

September 28, 2026

AWS

Security

Tutorials

Finding AWS Unrestricted Outbound Access in 2026: EC2, Lambda, and Beyond

Find EC2, Lambda, and ECS Fargate resources with unrestricted outbound access in AWS using SQL. Why egress controls still break attack chains in 2026.

Joe Karlsson

Joe Karlsson

May 5, 2026

AWS

Security

Tutorials

AWS IAM Identity Center with Google Workspace as an IdP: 2026 Step-by-Step Guide

Set up AWS IAM Identity Center with Google Workspace: SAML authentication, SCIM user provisioning, and group sync with CLI or ssosync. Updated for 2026.

Joe Karlsson

Joe Karlsson

May 5, 2026

AWS

Best Practices

Security

AWS CIS Benchmark in 2026: Automated Compliance with SQL-Based Policies

AWS CIS Benchmark hit v3.0 in 2024 with 40+ controls. Run automated compliance checks using SQL policies with exception management and multi-account views.

Joe Karlsson

Joe Karlsson

May 5, 2026

AWS

Cloud Infrastructure

Security

Tutorials

Integrate AbuseIPDB Threat Intelligence with CloudQuery

Enrich your cloud asset inventory with AbuseIPDB threat intelligence to identify public cloud IPs with known abuse reports.

Joe Karlsson

Joe Karlsson

April 20, 2026

AWS

Security

Tutorials

AWS IAM Identity Center (Formerly AWS SSO): The Complete 2026 Guide

AWS IAM Identity Center replaced AWS SSO in 2022. Learn how to set it up, configure permission sets, use the AWS CLI, and audit access with CloudQuery.

Joe Karlsson

Joe Karlsson

April 6, 2026

AWS

Security

AWS Delegated Administrator: Setup Guide

Set up AWS Delegated Administrator across 37+ services. Covers CLI and Terraform setup, IAM policies, delegation patterns, and auditing with CloudQuery.

Jason Kao

Jason Kao

February 25, 2026

AWS

Security

Tutorials

Set Up AWS CLI with SSO (IAM Identity Center) — Step by Step

Set up AWS CLI v2 with IAM Identity Center in 5 minutes. Covers SSO registration scopes, sso-session config, token refresh, and multi-account profiles.

Yevgeny Pats

Yevgeny Pats

February 25, 2026

AWS

Cloud Infrastructure

Security

CodeBreach Vulnerability: How to Detect If Your AWS CodeBuild Projects Are Affected

Detect CodeBreach vulnerability in your AWS CodeBuild webhook filters. SQL queries to find unanchored ACTOR_ACCOUNT_ID patterns and missing security controls.

Joe Karlsson

Joe Karlsson

January 21, 2026

Own your pipeline.
Own your data.