PRACTITIONER GUIDE | CLOUD SECURITY
Practitioner GuideUpdated 13 min read

Enforcing IMDSv2 Across Your Entire AWS Estate: The Practical Migration Guide

IMDSv1
was the credential theft vector in the Capital One breach (2019, 100M+ records) and in the May 2026 TanStack payload stealing AWS keys from developer machines
1 request
is all IMDSv1 requires to return IAM role credentials, no session token, no header, directly queryable with curl
0 hops
TTL on the IMDSv2 session token request prevents SSRF attacks from reaching the metadata service across network boundaries

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

The AWS EC2 Instance Metadata Service (IMDS) is how instances retrieve their IAM role credentials, instance identity, and configuration data. IMDSv1 responds to any GET request from the instance with no authentication, a single curl command from inside the instance returns the IAM credentials for the attached role. IMDSv2 requires a session token obtained via a PUT request with a TTL of 1, preventing SSRF attacks from traversing network hops to reach the metadata endpoint. Enforcing IMDSv2 is one of the highest-ROI cloud security controls available, but most environments still have IMDSv1-enabled instances because nobody has documented how to do the migration without breaking things.

Why IMDSv1 Is Still Everywhere Despite Being Dangerous

AWS released IMDSv2 in November 2019, the same year as the Capital One breach that exploited IMDSv1 via an SSRF vulnerability in a WAF. AWS has nudged customers toward IMDSv2 ever since but never forced the migration, because doing so would break a significant number of running applications.

The breakage risk is real. Applications that query the metadata service for credentials include: older AWS SDK versions (pre-2018), custom scripts that directly curl 169.254.169.254 for instance metadata, container workloads that use instance role credentials without the SDK abstraction layer, and tools that pull from the metadata service at startup before the application code runs.

The result is that most AWS environments have a mix of instances: new workloads that use IMDSv2, old workloads that still use v1, and nobody knows which is which. Enforcing IMDSv2 via a Service Control Policy without auditing first breaks production workloads.

Step 1: Find Every IMDSv1-Enabled Instance Across Your Estate

AWS Config has a managed rule that checks this: ec2-imdsv2-check. Enable it across all regions and accounts in your organization via a conformance pack, or deploy it via AWS Security Hub's EC2 controls (EC2.8: EC2 instances should use IMDSv2).

For a faster point-in-time check without waiting for Config to evaluate:

aws ec2 describe-instances \
  --query 'Reservations[].Instances[?MetadataOptions.HttpTokens!=`required`].[InstanceId,Tags[?Key==`Name`].Value|[0],MetadataOptions.HttpTokens]' \
  --output table

This returns every instance where HttpTokens is not required, meaning IMDSv1 is still accessible. Run this in every region. For multi-account organizations, use AWS Organizations with the AWS CLI profile chaining, or deploy this as a Lambda that iterates over all accounts via the Organizations API.

Sort the results by instance age and tag. Older instances (launched before 2020) are more likely to run software that queries v1. Instances tagged as dev or test are safer to migrate first.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

Step 2: Identify Which Applications Actually Query IMDSv1

Before disabling v1 on any instance, enable IMDSv2 in optional mode, meaning v2 is available but v1 still works. Then check CloudWatch metrics to see whether v1 is being used:

AWS publishes two CloudWatch metrics per instance:

  • MetadataNoToken: requests using IMDSv1 (no session token)
  • MetadataWithToken: requests using IMDSv2

Enable this monitoring by setting HttpPutResponseHopLimit to 2 (or your required value) and HttpTokens to optional on each instance. After 7 to 14 days of production traffic, check MetadataNoToken. If it is zero, the instance is safe to migrate to required. If it is non-zero, something on that instance is still calling v1.

To identify exactly what is making v1 calls on a given instance:

sudo tcpdump -i lo -n 'host 169.254.169.254 and port 80' -w /tmp/imds.pcap

Capture for 60 seconds during normal operation, then read the capture to see which processes are making HTTP (not HTTPS) GET requests to 169.254.169.254 without a PUT session token request preceding them.

Step 3: Fix Applications Before Enforcing

The most common sources of IMDSv1 calls and their fixes:

Old AWS SDK versions: boto3 before 1.9.0 and the AWS CLI before 1.16.0 do not support IMDSv2. Update the SDK. For Lambda, update the runtime. For EC2 instances, update via your package manager.

Direct curl to metadata endpoint: Any script with curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ needs to be updated to use the session token flow:

TOKEN=$(curl -s -X PUT 'http://169.254.169.254/latest/api/token' \
  -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600')
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/

Kubernetes node metadata access: Pods that use kiam, kube2iam, or the AWS VPC CNI to access instance credentials need their configurations updated. In kiam and kube2iam, update to versions that support IMDSv2 token passing. In EKS with the VPC CNI, ensure you are on CNI version 1.11 or later.

Step 4: Enforce IMDSv2 at Scale via Service Control Policy

Once you have migrated all applications on an instance to use IMDSv2, flip the instance-level setting:

aws ec2 modify-instance-metadata-options \
  --instance-id i-xxxxxxxxx \
  --http-tokens required

For enforcing that all new instances launch with IMDSv2 required, use a Service Control Policy. This SCP denies launching any EC2 instance without IMDSv2 required:

{
  "Effect": "Deny",
  "Action": "ec2:RunInstances",
  "Resource": "arn:aws:ec2:*:*:instance/*",
  "Condition": {
    "StringNotEquals": {
      "ec2:MetadataHttpTokens": "required"
    }
  }
}

Apply this SCP to all OUs in your organization except a break-glass OU for legacy workloads still being migrated. Set a deadline for migrating remaining v1 workloads and remove them from the exception OU as each one is fixed.

IMDSv2 Enforcement for Containers and Lambda

ECS tasks on EC2 launch types inherit the instance's IMDS settings. If the underlying EC2 instance requires IMDSv2, task metadata queries use v2. Set HttpPutResponseHopLimit to 2 for ECS instances to allow containers to reach the metadata service (the default TTL of 1 is consumed by the first network hop from container to host).

Lambda does not use IMDS, Lambda functions receive credentials through the Lambda execution environment, not through 169.254.169.254. Lambda is not affected by IMDS enforcement.

EKS pods using the AWS VPC CNI and IRSA (IAM Roles for Service Accounts) do not use the instance metadata service for credentials, they use the EKS OIDC provider. These pods are unaffected by IMDSv2 enforcement. Pods that do not use IRSA and fall back to the instance role are the ones that may be making v1 calls.

The bottom line

IMDSv2 enforcement is a two-phase operation: audit and migrate first, enforce second. Skipping the audit and jumping straight to an SCP breaks production workloads and creates emergency exceptions that never get cleaned up. The monitoring approach, optional mode plus CloudWatch MetadataNoToken metrics, tells you exactly which instances are safe to migrate before you touch them.

Frequently asked questions

What is the EC2 Instance Metadata Service and why does it exist?

IMDS is an HTTP endpoint at 169.254.169.254 that EC2 instances use to retrieve their configuration: IAM role credentials, instance identity document, user data, and placement information. It is only accessible from within the instance. Applications use it to get temporary AWS credentials without needing long-lived access keys embedded in code.

Can an external attacker reach IMDS directly?

Not directly, IMDS is only accessible from within the instance. The attack vector is SSRF (Server-Side Request Forgery): if your application accepts a URL as input and makes a server-side HTTP request to it, an attacker can provide 169.254.169.254 as the target URL. The server then fetches the IAM credentials and returns them to the attacker. IMDSv2 blocks this because the SSRF response cannot include a PUT request with a TTL header.

Does enforcing IMDSv2 affect Lambda functions?

No. Lambda functions do not use the EC2 IMDS at all, they receive credentials through the Lambda runtime environment via a different mechanism. IMDSv2 enforcement only affects EC2 instances and workloads running on EC2 (ECS on EC2, self-managed Kubernetes on EC2).

What hop limit should I set for ECS containers?

Set HttpPutResponseHopLimit to 2 for ECS EC2 instances. The default of 1 means the PUT session token request is consumed at the first network hop (container-to-host bridge), and the container never receives the token. Setting it to 2 allows the request to traverse one bridge interface and reach the metadata service.

How do I check if a specific instance is using IMDSv1 or v2?

Run: aws ec2 describe-instances --instance-ids i-xxxxxxxxx --query 'Reservations[].Instances[].MetadataOptions'. The HttpTokens field shows optional (v1 still accessible) or required (v2 only). The MetadataNoToken CloudWatch metric for that instance shows you how many v1 requests have been made recently.

How do you detect and alert on IMDSv1 usage across your AWS fleet before enforcing IMDSv2 so you can identify applications that will break at cutover?

The MetadataNoToken CloudWatch metric, published per instance under the AWS/EC2 namespace, records every unauthenticated (IMDSv1) metadata request. Create a CloudWatch Metric Alarm or use a CloudWatch Logs Insights query across all instances to surface any with MetadataNoToken greater than zero in the last 7 days. Pipe that output to a Lambda that cross-references each instance ID against your CMDB tags (team, application, environment) and opens a Jira ticket for the owning team to migrate their application to an IMDSv2-aware SDK or curl call. Set a 30-day migration SLA per ticket before enforcement begins. Do not enforce IMDSv2 (HttpTokens: required) on an instance until MetadataNoToken has been zero for at least 7 consecutive days, confirming no active application path is using the v1 endpoint.

Sources & references

  1. AWS IMDSv2 documentation
  2. AWS Security blog: IMDSv2 enforcement
  3. AWS Config IMDSv2 conformance pack

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.