Does BYOC Work With IMDSv2 Required?
Yes. Require IMDSv2 is a documented per-runner setting on AWS BYOC custom runners, so GitHub Actions jobs read instance credentials only with a session token.
Answer
Yes. The AWS BYOC configuration guide documents Require IMDSv2 as a setting on the custom runner: both IMDS v1 and v2 answer by default, and you switch a runner to the session-token version from the Update Runner page under Runner Specs, with the same field available when you first create the runner (AWS BYOC configuration).
The security hardening guide lists the same toggle as hardening step 6 and ends its checklist with the line "IMDSv2 required on all runners". The setting lands on the runner class rather than on the stack, so one stack can carry a hardened runner and an unmodified one while you work through the rollout. Nothing in the workflow changes: the runs-on label stays the same, and the EC2 instance WarpBuild launches for the job comes up with the metadata service configured the way that runner class specifies.
Detail
Where the setting lives
| Item | Value |
|---|---|
| Default on a new custom runner | Both IMDS v1 and v2 answer |
| Where the field lives | Custom runner configuration, Runner Specs section, "Require IMDSv2" |
| When you can set it | At runner creation, and later on the Update Runner page |
| Scope | One runner class, so classes in the same stack decide independently |
| What it applies to | The EC2 instances launched in your AWS account for jobs on that class |
Rows come from the AWS BYOC configuration guide, checked on 2026-08-13. Because each job runs on a freshly provisioned instance that is terminated when the job finishes, the change takes effect on the next job queued to that class rather than needing a fleet restart (security hardening guide).
Why the session-token version matters
Version 1 answers a plain GET to the link-local address. Version 2 makes the caller open a session first: a PUT to /latest/api/token returns a token, and every later GET carries that token in a header. AWS also has the endpoint reject requests carrying X-Forwarded-For and applies a hop limit to the response (AWS instance metadata service configuration).
Those three properties close the request-forgery path. A service on the instance that can be tricked into fetching an attacker-supplied URL will happily fetch the credentials path under version 1 and hand back the body. Under version 2 the same trick fails, because the forged request is a GET with no session token and no way to add the header. The WarpBuild security guide states the defense in exactly those terms: require IMDSv2 to protect against attacks that attempt to steal instance credentials (security hardening guide).
The value of the setting scales with what the runner can reach. A runner class with no instance profile has no role credentials at the endpoint to steal. A class carrying an ECR push profile or a deploy profile does, and that is the class to harden first (instance profile setup).
Check your build tools before you enforce it fleet wide
Enforcement is a one-click change with a blast radius equal to every tool on the machine that reads metadata. Work through the consumers first.
| Metadata consumer | What to check | Typical outcome |
|---|---|---|
| AWS CLI and AWS SDKs in the runner image | Version currency; current releases request a token before reading credentials | Works unchanged |
Shell steps calling 169.254.169.254 directly | Whether the curl command sends a token header | Fails until the PUT is added |
| Agents baked into a custom AMI | Whether the vendor build supports the session-token version | Vendor-dependent, so test it |
| Steps reading metadata from inside a container | Whether the extra network hop still reaches the endpoint under the documented hop limit | Test before enforcing |
A probe job settles the question in one run. Point it at the class you just changed:
name: imds-probe
on: workflow_dispatch
jobs:
probe:
runs-on: warp-custom-build-use1-8x
steps:
- name: Read credentials with a session token
run: |
TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 300")
curl -sf -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/
- name: Fail if a tokenless read still works
run: |
if curl -sf --max-time 2 http://169.254.169.254/latest/meta-data/ > /dev/null; then
echo "the metadata service still answers without a token" >&2
exit 1
fi
- name: Run the real build steps
run: make buildThe first step proves the credential path your jobs depend on still resolves. The second proves the old path is closed. The third catches the tools you forgot about, which is the failure everyone actually hits.
Before the switch, AWS publishes a per-instance CloudWatch metric that counts metadata calls made without a token, which is the way to find version 1 callers while they are still succeeding (AWS instance metadata service configuration). A workable order is: enable on one low-traffic runner class, run the probe, leave it for a day of real jobs, then move through the remaining classes and tick the checklist line on the security checklist for BYOC on AWS. The longer setup walkthrough lives on requiring IMDSv2 on BYOC runners, and the endpoint itself is defined on instance metadata service.
What the hardening costs
Nothing on top of the runner rate. BYOC Linux runners and BYOC Windows runners both bill $0.002 per runner minute in WarpBuild fees, and AWS bills your own account for the EC2 capacity those jobs consume (pricing page, checked on 2026-08-13).
BYOC runs on AWS, GCP, and Azure, so read this setting as the AWS-specific one in a wider set of metadata endpoints.
Related Questions
Does requiring IMDSv2 break jobs that use an instance profile?
No, as long as the tools reading credentials request a session token first. Current AWS SDKs and the AWS CLI do that automatically, so a job that assumes its role through the instance profile keeps working (instance profile setup). What breaks is a script that curls http://169.254.169.254 with no token header, or an agent baked into a custom image that still speaks the single-request version. The probe job above finds both in one run.
Can I require it on some runners and not others?
Yes. Require IMDSv2 sits on the custom runner configuration under Runner Specs, so each runner class in a stack decides independently (AWS BYOC configuration). Enable it on one low-traffic class, run a probe job, then work through the rest of the fleet. The class-by-class walkthrough is on requiring IMDSv2 on BYOC runners.
What about GCP and Azure BYOC runners?
BYOC runs on AWS, GCP, and Azure. The Require IMDSv2 toggle documented by WarpBuild is the AWS one, and GCP and Azure expose their own metadata endpoints with their own required request headers, so the compatibility check has to be run per cloud. The shared concept behind all three is covered on instance metadata service, and the AWS stack layout is on the AWS BYOC page.
Start with $10 in free credits
Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.