The EC2 Instance Metadata Service (IMDS) sits at 169.254.169.254 on every EC2 instance and hands out instance identity, configuration, and — most critically — IAM role credentials to any process that can reach it. In IMDSv1, that means any HTTP client on the instance can retrieve credentials with a simple GET request. For a web application running on EC2, this is a serious problem: if the application has a server-side request forgery vulnerability, an attacker who can make the application fetch an arbitrary URL can retrieve instance credentials, assume the EC2 instance's IAM role, and take actions in your AWS account.
IMDSv2 addresses this by requiring a session-oriented request flow. Before accessing instance metadata, a client must PUT a request to the metadata service to obtain a session token. The token is then included in subsequent GET requests. This PUT/GET sequence breaks SSRF-based metadata theft because most SSRF vulnerabilities only allow GET requests — the attacker can make the vulnerable application fetch a URL but cannot make it execute the two-step session initiation.
Why IMDSv1 Is Still in Use
IMDSv2 was released in November 2019. The fact that many accounts still have instances running IMDSv1 in 2026 reflects two realities: the migration isn't free of application impact, and AWS didn't force the migration for years. AWS eventually announced that all new instances would require IMDSv2 by default, but existing instances were grandfathered.
Applications that hit the metadata service directly via simple GET requests break when IMDSv2 is enforced. This includes older versions of the AWS SDKs (pre-2019 versions of boto3, the AWS Java SDK, etc.), custom scripts that curl the metadata endpoint, and some older EC2 user data patterns. Before enforcing IMDSv2 on any instance, you need to verify what's using the metadata service and whether it supports the token-based flow.
Auditing IMDSv1 Usage
Start by understanding the current state. The EC2 console and CLI show which instances have IMDSv2 optional versus required. Run the following CLI command to find instances where IMDSv1 is still permitted:
aws ec2 describe-instances --query 'Reservations[].Instances[?MetadataOptions.HttpTokens==`optional`].[InstanceId,Tags[?Key==`Name`].Value|[0],Placement.AvailabilityZone]' --output table
This gives you a list of every instance where IMDSv1 requests are accepted. The list is often longer than expected — AMIs created before IMDSv2 default to optional tokens, and launch templates created before the enforcement date carry the old default unless explicitly updated.
Before migrating each instance, check whether it's actually using IMDSv1. Enable IMDS request metrics in CloudWatch by setting HttpPutResponseHopLimit to 1 and watching the MetadataNoToken CloudWatch metric. This metric increments every time the metadata service receives a request without a token — indicating that IMDSv1 is being used. Zero MetadataNoToken requests over several days means it's safe to enforce IMDSv2 for that instance.
Enforcing IMDSv2 Without Breaking Applications
The migration has two components: enforcing IMDSv2 on running instances and updating launch templates and AMIs so new instances launch with IMDSv2 required from the start.
For running instances, use the ModifyInstanceMetadataOptions API call to switch HttpTokens from optional to required. This takes effect immediately without requiring instance reboot. If an application breaks, you can revert to optional just as quickly. Do this during a maintenance window and monitor application error rates for 30 minutes before moving to the next instance.
aws ec2 modify-instance-metadata-options --instance-id i-0123456789abcdef0 --http-tokens required --http-endpoint enabled
For launch templates, update the MetadataOptions block to set HttpTokens to required. Any new instances launched from the updated template will enforce IMDSv2 from launch. For AMI-based deployments, bake the IMDSv2 requirement into the AMI creation process rather than relying on post-launch configuration.
Application Changes Required
If your applications are using AWS SDKs released after mid-2019, they support IMDSv2 automatically — the SDK's credential provider chain handles the token request transparently. The AWS CLI version 2 also handles IMDSv2 natively. The cases that require code changes are:
- Direct HTTP calls to the metadata endpoint in scripts or application code (change GET to include the token header)
- Very old SDK versions that don't support IMDSv2 (upgrade the SDK)
- Container workloads using the metadata endpoint through a proxy that only supports GET
The IMDSv2 token request is a single additional HTTP call that adds negligible latency. The token is valid for up to 21600 seconds (6 hours), so applications that cache credentials don't need to re-fetch the token on every metadata request.
Preventing Regression with AWS Config
Once you've migrated all instances to IMDSv2, use AWS Config to detect any new instance that launches with IMDSv1 enabled. The managed Config rule ec2-imdsv2-check evaluates every EC2 instance and flags those with HttpTokens set to optional. Configure auto-remediation to enforce IMDSv2 on flagged instances, or configure alerting to notify your security team when a violation is detected.
At the account level, an SCP can prevent instances from being launched with IMDSv2 disabled:
{
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringEquals": {
"ec2:MetadataHttpTokens": "optional"
}
}
}
This SCP blocks any attempt to launch an instance without IMDSv2 required, regardless of who initiates the launch. Combined with ongoing Config monitoring, it ensures the account doesn't regress after the initial migration.
Related Reading
- IAM security monitoring — monitoring the permissions held by EC2 instance roles
- EC2 security groups audit — network-level controls that complement IMDS hardening
- Essential AWS Config rules — building a complete EC2 security baseline
- GuardDuty finding types — detecting credential use from compromised EC2 instances
FAQ
Does IMDSv2 affect ECS tasks or Lambda functions?
ECS tasks on EC2 launch type use their own task metadata endpoint (169.254.170.2) rather than the EC2 IMDS, so IMDSv2 enforcement doesn't directly affect ECS task credential retrieval. Lambda functions don't have access to the EC2 IMDS at all — they receive credentials through the Lambda execution environment. IMDSv2 migration is specifically an EC2 concern.
What's the hop limit and why does it matter?
The HttpPutResponseHopLimit setting controls how many network hops the IMDSv2 PUT request can traverse. The default is 1, which means only processes on the instance itself can initiate the token request. Containers running on the instance also need to reach IMDS — setting the hop limit to 2 allows container processes one hop away from the instance to initiate sessions. Never set the hop limit above 2 in most configurations.
What if my container uses the EC2 metadata endpoint?
Containers that need EC2 instance metadata should use the IMDSv2 token flow. The container makes a PUT request to 169.254.169.254/latest/api/token with TTL headers to get a token, then uses that token in subsequent GET requests. If the container runtime sits behind a proxy that only supports GET, you'll need to update the proxy or switch to a metadata retrieval pattern that supports the session flow.
Protect your AWS accounts before it's too late
Vigilare monitors your AWS accounts for suspension risks — billing anomalies, IAM issues, GuardDuty findings, and more — and alerts you before AWS takes action.
Written by Vigilare Engineering
Platform Team