Skip to main content
INS // Insights

AWS IMDSv2 Enforcement So Metadata Stays Local

Updated October 2026 · 6 min read

AWS IMDSv2 enforcement closes the metadata path that turns a server-side request bug into cloud credentials. Instance Metadata Service version 1 answers a simple GET to 169.254.169.254 with the instance role keys. Version 2 requires the caller to PUT a session token first and send that token on the GET. A request that cannot set the X-aws-ec2-metadata-token header does not receive credentials. The buyer outcome is a fleet where HttpTokens is required, hop limit is deliberate, and a new instance cannot launch any other way.

Rutagon sets the flag on running instances, blocks launch templates that omit it, and files the Config compliance export in the GRC you already run when you treat this as a control. This is infrastructure engineering. It is not a penetration test and not a monitoring-service retainer.

What required tokens change

IMDSv2 session setup is a PUT to /latest/api/token with header X-aws-ec2-metadata-token-ttl-seconds. The response body is the token. Later calls send X-aws-ec2-metadata-token. The instance profile credentials still live at the metadata path. They are gated by that header. Applications that use the AWS SDK and a recent release already perform this exchange. Applications that use a hand-rolled HTTP GET to the metadata IP do not, and they are the inventory we want before the flag flips.

HttpPutResponseHopLimit decides how many network hops the token response may travel. A hop limit of 1 keeps the token on the instance. Containers that reach IMDS through an extra virtual hop, which is common for ECS on EC2 and some bridge networking, need a hop limit of 2 or the task cannot obtain role credentials. We set 1 as the default and record every 2 as an exception with the instance id and the reason. A fleet-wide hop limit of 2 "to be safe" widens the path the control was meant to shrink.

AWS documents the options in Configure the instance metadata service. The modify call we use:

aws ec2 modify-instance-metadata-options \
  --instance-id i-0123456789abcdef0 \
  --http-tokens required \
  --http-put-response-hop-limit 1 \
  --http-endpoint enabled

Disabling the metadata endpoint entirely is a stronger setting for instances that should not have a role. We do that when the instance profile is empty. An instance that needs the AWS API keeps the endpoint and requires tokens.

AWS IMDSv2 enforcement across the organization

Existing instances are the detective-then-fix half. Launch templates and Auto Scaling groups are the preventive half. A template that does not set MetadataOptions.HttpTokens to required will replace a patched instance with an open one at the next scale event. We update the template and the ASG version in the same change as the running instances.

The organization guard is a service control policy, in the spirit of SCP least privilege. Deny ec2:RunInstances when the request does not set ec2:MetadataHttpTokens to required. Deny ec2:ModifyInstanceMetadataOptions that would set tokens back to optional, except for a narrow break-glass role. The condition key is ec2:MetadataHttpTokens. A policy that only alarms after launch leaves a window. The SCP closes the window for new instances.

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

AWS Config rule ec2-imdsv2-check remains, because SCP does not rewrite instances that already exist and because exceptions at hop limit 2 still need a list. The compliance export is what we file. VPC security group practice is adjacent and does not substitute. A tight security group does not stop a process on the instance from calling the metadata IP.

We roll by target group. A canary ASG first, application logs watched for metadata failures, then the rest. The failure looks like expired or missing credentials inside the app, not like a network ACL deny. Warning the owner before the flag flips is part of the job. Surprising a payments service at the end of a sprint is how the flag gets reverted.

Exceptions we will actually write down

Hop limit 2 for a named container host pattern is a written exception, not a console drift. The exception names the AMI or launch template, the hop limit, and the owner. It expires when that platform can use a hop limit of 1 or when the workload moves to a model that does not need IMDS from inside the container, such as a task role injected by the control plane.

Instances in the middle of a blue/green cut get a short exception window. The end state is still required. We do not leave "optional" on the old template because rollback might need it. Rollback uses a template that also requires tokens, which means the SDK fix lands before enforcement. That sequencing is the production lesson. Enforcement first, code never, is how you get a Friday revert.

Marketplace AMIs and vendor agents sometimes ship an IMDSv1-only helper. Those show up in the canary. The vendor gets a hop-limit exception only if the helper cannot be configured, and the instance profile on that host is stripped to the minimum the agent needs. A wide role plus IMDSv1 is the combination we refuse to grandfather.

AWS Verified Access and Session Manager remove other reasons people poke at instances. They do not replace IMDSv2. Any remaining instance role is still reachable from local metadata if version 1 is on. We treat them as separate controls in the same account hardening pass.

Evidence

The packet is the SCP, the launch template metadata options, the Config rule compliance snapshot, and the exception list for hop limit 2. We file it in the GRC you already run when this control is in your system description. The operational outcome does not depend on the audit: new instances require tokens, and old instances are flipped after the canary. Rutagon does not hold your compliance attestation. We change the metadata options and the guardrail that keeps them changed.

Account baselines belong in the landing zone so a new account does not arrive with optional tokens. The SCP at the organization root is that baseline. Per-account console clicks will drift.

Frequently Asked Questions

What does HttpTokens required actually block?

It blocks metadata calls that do not present a session token from the IMDSv2 PUT. A simple GET for instance role credentials fails. SDKs that already exchange a token keep working. Custom scripts that GET the metadata IP directly need a change before you enforce.

Why is the hop limit usually 1?

Hop limit 1 keeps the token response on the instance. Containers on an extra network hop often need 2 or they cannot assume the instance role. We default to 1 and record each 2 with an owner. A blanket hop limit of 2 undoes part of the control.

How do you stop the next Auto Scaling launch from reverting?

The launch template sets HttpTokens to required, and an SCP denies RunInstances when ec2:MetadataHttpTokens is not required. Patching a running instance and leaving the template alone loses the setting at the next scale-out.

What breaks first when you enforce?

Applications with a hand-rolled metadata client, and containers whose hop limit is too low for their network mode. We canary one group and read credential errors before the rest of the fleet. The AWS SDK path is the one we expect to stay quiet.

Where is the control recorded?

The SCP, the template settings, the Config compliance snapshot, and the hop-limit exceptions are filed in the GRC you already run. Rutagon implements the enforcement. We do not provide the attestation and we do not operate a monitoring center.

Talk to us about enforcing IMDSv2 across the accounts you already run. Contact Rutagon at rutagon.com/contact, 907-841-8407, or contact@rutagon.com.