EC2 launch templates should use Instance Metadata Service Version 2 (IMDSv2)
The EC2 metadata service at 169.254.169.254 hands out temporary IAM credentials, instance identity documents, and user data scripts to anyone who asks. IMDSv1 asks for nothing in return: any HTTP GET works. A vulnerable web app, a misconfigured proxy, or a basic SSRF payload is enough to retrieve credentials in seconds.
IMDSv2 requires a session token obtained via a PUT request with a TTL header. Most SSRF vectors can't issue PUT requests or forward arbitrary headers, which cuts the attack chain at the source. Setting this at the launch template level means every instance launched from it inherits the protection automatically, without relying on individual teams to remember the flag at launch time.
Retrofit consideration
Existing workloads using IMDSv1 SDK calls (AWS SDKs before mid-2019, custom scripts issuing plain GET requests to 169.254.169.254) will break when HttpTokens is switched to required. Check the CloudWatch metric MetadataNoToken on affected instances before enforcing.
Implementation
Choose the approach that matches how you manage Terraform.
If you use terraform-aws-modules/autoscaling/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "autoscaling" {
source = "terraform-aws-modules/autoscaling/aws"
version = ">=9.0.0"
image_id = "ami-abc12345"
instance_type = "t4g.nano"
max_size = 1
min_size = 0
name = "abc123"
network_interfaces = [
{
associate_public_ip_address = false
security_groups = ["sg-12345678"]
subnet_id = "subnet-12345678"
}
]
vpc_zone_identifier = ["subnet-12345678"]
metadata_options = {
http_tokens = "required"
}
}
Use AWS provider resources directly. See docs for the resources involved: aws_launch_template.
resource "aws_launch_template" "this" {
name_prefix = "pofix-abc123-"
network_interfaces {
associate_public_ip_address = "false"
subnet_id = "subnet-12345678"
}
metadata_options {
http_tokens = "required"
}
}
What this control checks
The aws_launch_template resource must include a metadata_options block with http_tokens set to "required". When http_tokens is omitted or set to "optional", the control fails because instances launched from the template accept IMDSv1 requests.
Set http_endpoint to "enabled" (the default) to keep the metadata service available. Setting http_put_response_hop_limit to 1 prevents containers and multi-hop network paths from reaching the endpoint, though that is outside the scope of this control.
Evaluation targets the default version of the launch template, identified by default_version or update_default_version = true. New versions created without a metadata_options block do not inherit the setting from previous versions, so the default version must explicitly carry http_tokens = "required".
Common pitfalls
Omitting metadata_options defaults to IMDSv1 allowed
metadata_options { http_tokens = "required" }must be explicit. Omit the block entirely and AWS defaultsHttpTokenstooptional, IMDSv1 is permitted, and the control fails. There is no implicit inheritance.New launch template versions may not inherit metadata_options
Terraform does not carry
metadata_optionsforward automatically when you restructure a resource block. Addupdate_default_version = trueand reorganize the block, and the new default version can silently drop thehttp_tokenssetting. Always include the block explicitly in every version definition.Auto Scaling Groups pinned to a specific version
An
aws_autoscaling_groupthat pins a specific launch template version number ignores changes to the default version entirely. Updating the default to require IMDSv2 has no effect on that ASG or the instances it launches. Reference$Defaultinstead, or update the pinned version directly.SDK and application compatibility with IMDSv2
AWS SDK versions from before mid-2019 use IMDSv1 GET calls for credential retrieval. Flipping
http_tokenstorequiredon instances running those SDKs causes credential failures immediately. CheckMetadataNoTokenin CloudWatch before enforcing this on existing workloads.
Audit evidence
The primary artifact is aws ec2 describe-launch-template-versions --launch-template-id <id> --versions $Default showing MetadataOptions.HttpTokens as required for every in-scope launch template. Config rule results for ec2-launch-template-imdsv2-check support this, and Security Hub or a CSPM tool provides continuous pass/fail status across the account.
For change history, CloudTrail events for CreateLaunchTemplate and CreateLaunchTemplateVersion should show the MetadataOptions parameter in each request. A non-default version with HttpTokens set to optional does not fail this control unless it is promoted to the default version.
Framework-specific interpretation
Related controls
EC2 instances should use IAM instance roles for AWS resource access
ECS fargate services should run on the latest fargate platform version
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
ec2_launch_template_default_version_uses_imdsv2AWS Config Managed Rule:
EC2_LAUNCH_TEMPLATE_IMDSV2_CHECKCheckov Check:
CKV_AWS_79Powerpipe Control:
aws_compliance.control.ec2_launch_template_default_version_uses_imdsv2Prowler Check:
ec2_launch_template_imdsv2_requiredAWS Security Hub Controls:
EC2.170,EC2.8KICS Query:
c306ac53-ee5b-41d3-86a9-0fd2722b4e67
Last reviewed: 2026-03-09