aws-emr-exposes-instance-profile-cred
Every EC2 node in an EMR cluster exposes the instance profile (JobFlowRole) credentials via the EC2 Instance Metadata Service (IMDS); any code running on the cluster can retrieve them.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?cluster) ==
AnalyticsService
?cluster provider_type == AWS::EMR::Cluster
emit
| source type | AnalyticsService |
|---|---|
| target type | Identity |
| source | ?cluster |
| target | ?role |
| conditions | service_state |
| state logic | ACTIVE when the cluster is in RUNNING/WAITING state. CONDITIONAL(condition_expression) when IMDSv2 with HttpPutResponseHopLimit=1 is enforced on all cluster instances (reduces but does not eliminate risk — hop-limit enforcement is per-instance and does not apply retroactively). Do NOT mark BLOCKED solely on IMDSv2: containerized or privileged steps may still bypass the hop-limit; analysts should verify instance metadata options explicitly. |
Narrative
EMR cluster {cluster.name} exposes the credentials of its instance profile role {role.name} via IMDS (http://169.254.169.254) on every EC2 node; any code executing on the cluster (including submitted steps) can retrieve those credentials without additional permissions.
Raw rule rules/derived/aws/emr.yaml
id: aws-emr-exposes-instance-profile-cred
emits: ExposesCredential
description: Every EC2 node in an EMR cluster exposes the instance profile (JobFlowRole) credentials via
the EC2 Instance Metadata Service (IMDS); any code running on the cluster can retrieve them.
match:
- - cluster: null
- ExecutesAs
- role: null
where:
- node_type(?cluster) == AnalyticsService
- ?cluster provider_type == AWS::EMR::Cluster
emit:
source_type: AnalyticsService
target_type: Identity
source: ?cluster
target: ?role
permissions: []
conditions:
- service_state
state_logic: "ACTIVE when the cluster is in RUNNING/WAITING state. CONDITIONAL(condition_expression)\
\ when IMDSv2 with HttpPutResponseHopLimit=1 is enforced on all cluster instances (reduces but does\
\ not eliminate risk \u2014 hop-limit enforcement is per-instance and does not apply retroactively).\
\ Do NOT mark BLOCKED solely on IMDSv2: containerized or privileged steps may still bypass the hop-limit;\
\ analysts should verify instance metadata options explicitly."
derived_from:
- <ExecutesAs(aws-emr-executes-as-instance-profile) edge_id>
false_positive_note: "This is a structural fact: the IMDS credential-exposure is inherent to EMR EC2\
\ clusters. It is not an escalation by itself \u2014 it becomes an attack step when combined with\
\ a CanModifyCode/AddJobFlowSteps edge (code gets on the cluster and reads IMDS). Do not BLOCK solely\
\ on IMDSv2 \u2014 downgrade to CONDITIONAL(condition_expression) only when IMDSv2 hop-limit=1 is\
\ confirmed on all nodes. EMR Serverless does NOT use IMDS; this rule does not apply to Serverless\
\ job runs."
narrative: EMR cluster {cluster.name} exposes the credentials of its instance profile role {role.name}
via IMDS (http://169.254.169.254) on every EC2 node; any code executing on the cluster (including
submitted steps) can retrieve those credentials without additional permissions.