[security] Non-admin broker leases can select AWS security groups, subnets, AMIs, and instance profiles
Summary
The brokered AWS lease creation path accepts provider-resource selectors from any authenticated lease request and applies them under the coordinator's AWS principal. A non-admin caller can set awsSGID, awsSubnetID, awsAMI, and awsProfile in POST /v1/leases; leaseConfig() preserves those values, and the AWS provider later uses them for DescribeSecurityGroups, SSH ingress reconciliation, RunInstances, AMI selection, subnet placement, and instance-profile attachment.
This crosses Crabbox's supported coordinator authorization boundary when the broker AWS principal can touch resources beyond the broker-managed runner group and default network. SECURITY.md treats coordinator authentication, ownership, and sharing controls as product boundaries, and lists non-admin escalation plus unsafe provider-resource mutation as in-scope. This is not a hostile-tenant isolation claim or a trusted operator running commands on their own lease; it is a non-admin request causing the privileged broker to operate on caller-selected AWS resources.
Affected Components
- Target commit:
6dba4afd1c5a4be0a780cf035d1b397e8982d478
- Component: Cloudflare Durable Object coordinator AWS lease creation.
worker/src/fleet.ts:1604-1671 parses the lease request, builds config, and gates snapshot-backed lease sources plus hostID / awsMacHostID behind admin auth, but does not gate awsSGID, awsSubnetID, awsAMI, or awsProfile.
worker/src/config.ts:281-288 copies awsAMI, awsSnapshot, awsSGID, awsSubnetID, and awsProfile directly from request input into the lease config.
worker/src/aws.ts:66-75 prefers config.awsSGID over the broker's CRABBOX_AWS_SECURITY_GROUP_ID.
worker/src/aws.ts:1206-1298 uses the selected security group for DescribeSecurityGroups, stale SSH ingress pruning, and AuthorizeSecurityGroupIngress.
worker/src/aws.ts:1053-1094 uses config.awsProfile and config.awsSubnetID as IamInstanceProfile.Name and NetworkInterface.1.SubnetId in RunInstances.
worker/src/aws.ts:1148-1150 uses config.awsAMI before the broker default AMI.
internal/cli/coordinator.go:799-831 forwards these config values to POST /v1/leases.
Attack Path
Attacker role: authenticated non-admin broker user, including a normal signed user token or shared operator token.
Prerequisites:
- The deployment enables brokered AWS leases.
- The broker AWS principal has permissions broad enough to describe or modify the caller-selected security group, launch in the caller-selected subnet, pass the caller-selected instance profile, or boot the caller-selected AMI.
- The attacker can submit a normal lease creation request.
Steps:
- Send
POST /v1/leases for provider aws with caller-chosen values such as awsSGID, awsSubnetID, awsAMI, awsProfile, and attacker-controlled awsSSHCIDRs.
fleet.ts builds a lease config and only rejects non-admin snapshot sources or dedicated-host pins. The AWS selector fields remain in the config.
awsConfiguredSecurityGroupID() returns the request's awsSGID, so ensureSecurityGroup() describes that group and reconciles SSH ingress against the request's source CIDRs.
createServer() places awsProfile into IamInstanceProfile.Name, places awsSubnetID into NetworkInterface.1.SubnetId, and calls RunInstances with the selected AMI.
Result: if the broker IAM permits those AWS actions, a non-admin Crabbox caller can make the broker add SSH ingress to a security group the operator did not intend Crabbox to manage, launch instances in a caller-selected subnet, attach a caller-selected instance profile, or boot a caller-selected AMI.
Impact
This gives a non-admin broker user partial control over AWS resources and launch identity that are normally governed by the broker operator. In affected deployments, the user can widen SSH reachability on non-managed security groups or launch broker-paid instances with network placement, image, and instance-profile choices that the broker operator did not approve.
The strongest impact is credential and privilege exposure through an attacker-selected instance profile, because the launched machine can receive AWS role credentials intended for a different workload. Security-group and subnet selection can also expose existing network boundaries or place Crabbox instances into unintended VPC segments. The issue is deployment-dependent: least-privilege broker IAM limited to Crabbox-managed resources reduces or prevents exploitation, but the product currently does not fail closed before making the privileged AWS calls.
Severity Assessment
CVSS Assessment
| Metric |
v3.1 |
v4.0 |
| Score |
7.1 / 10.0 |
6.1 / 10.0 |
| Severity |
High |
Medium |
| Vector |
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N |
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:L/VA:L/SC:L/SI:L/SA:L |
| Calculator |
CVSS v3.1 Calculator |
CVSS v4.0 Calculator |
The v3.1 vector uses high attack complexity because practical exploitation depends on the broker AWS principal having authority over the selected resources. The v4.0 vector records that deployment precondition as AT:P. The primary risk is confidentiality exposure from attaching an unintended instance profile, with lower integrity and availability effects from unauthorized security-group and placement changes.
Recommended Remediation
Fail closed in createLease() before provider preparation for non-admin AWS resource selectors that can redirect the broker AWS principal:
- Reject non-empty
awsSGID from non-admin requests unless it matches an operator-approved broker value.
- Reject non-empty
awsSubnetID from non-admin requests unless it matches an operator-approved broker value.
- Reject non-empty
awsProfile from non-admin requests unless it is in an operator-maintained allowlist.
- Reject non-empty
awsAMI from non-admin requests unless it is selected through Crabbox's promoted image flow or an operator-maintained allowlist.
Add regression coverage in worker/test/fleet.test.ts for non-admin POST /v1/leases requests containing each field. Existing tests already prove analogous admin-only behavior for hostID / awsMacHostID and snapshot-backed lease fields; the new tests should assert the same 403 admin_required behavior for these AWS selectors.
Validation
Validation method: source review of the latest verification checkout at commit 6dba4afd1c5a4be0a780cf035d1b397e8982d478; no live AWS calls were made.
Evidence:
SECURITY.md says coordinator authentication, ownership, and sharing controls remain product boundaries, and lists non-admin escalation and destructive provider actions against resources Crabbox cannot strongly identify as its own as in scope.
docs/security.md says brokered AWS leases otherwise scope SSH ingress to the CLI-detected or request-source CIDR, establishing that the broker owns this security posture for brokered leases.
docs/providers/aws.md documents the AWS selector fields as configuration, and notes that brokered AWS credentials live in the Worker rather than on developer machines. That means a brokered request uses the coordinator's AWS authority, not the user's local AWS authority.
worker/src/fleet.ts:1654-1671 contains admin checks for nearby high-risk lease sources and host pins, but no equivalent check for awsSGID, awsSubnetID, awsAMI, or awsProfile.
worker/src/config.ts:281-288 preserves the caller-supplied AWS fields.
worker/src/aws.ts:66-75, 1206-1298, 1053-1094, and 1148-1150 show those fields reaching AWS API parameters.
internal/cli/coordinator.go:799-831 confirms the CLI sends these values in broker lease creation requests.
Counterevidence considered:
- These fields are useful operator configuration knobs, and the direct-mode AWS path intentionally lets a trusted local operator choose them. That does not defeat the brokered finding because the brokered path uses the coordinator's AWS credentials for an authenticated non-admin request.
CRABBOX_AWS_SECURITY_GROUP_ID and managed security group names provide safer defaults when the request omits awsSGID, but awsConfiguredSecurityGroupID() gives request input priority.
- Least-privilege broker IAM can limit exploitability. This is reflected in the severity and prerequisites, but Crabbox still accepts and attempts privileged provider operations for non-admin caller-selected resources.
[security] Non-admin broker leases can select AWS security groups, subnets, AMIs, and instance profiles
Summary
The brokered AWS lease creation path accepts provider-resource selectors from any authenticated lease request and applies them under the coordinator's AWS principal. A non-admin caller can set
awsSGID,awsSubnetID,awsAMI, andawsProfileinPOST /v1/leases;leaseConfig()preserves those values, and the AWS provider later uses them forDescribeSecurityGroups, SSH ingress reconciliation,RunInstances, AMI selection, subnet placement, and instance-profile attachment.This crosses Crabbox's supported coordinator authorization boundary when the broker AWS principal can touch resources beyond the broker-managed runner group and default network.
SECURITY.mdtreats coordinator authentication, ownership, and sharing controls as product boundaries, and lists non-admin escalation plus unsafe provider-resource mutation as in-scope. This is not a hostile-tenant isolation claim or a trusted operator running commands on their own lease; it is a non-admin request causing the privileged broker to operate on caller-selected AWS resources.Affected Components
6dba4afd1c5a4be0a780cf035d1b397e8982d478worker/src/fleet.ts:1604-1671parses the lease request, buildsconfig, and gates snapshot-backed lease sources plushostID/awsMacHostIDbehind admin auth, but does not gateawsSGID,awsSubnetID,awsAMI, orawsProfile.worker/src/config.ts:281-288copiesawsAMI,awsSnapshot,awsSGID,awsSubnetID, andawsProfiledirectly from request input into the lease config.worker/src/aws.ts:66-75prefersconfig.awsSGIDover the broker'sCRABBOX_AWS_SECURITY_GROUP_ID.worker/src/aws.ts:1206-1298uses the selected security group forDescribeSecurityGroups, stale SSH ingress pruning, andAuthorizeSecurityGroupIngress.worker/src/aws.ts:1053-1094usesconfig.awsProfileandconfig.awsSubnetIDasIamInstanceProfile.NameandNetworkInterface.1.SubnetIdinRunInstances.worker/src/aws.ts:1148-1150usesconfig.awsAMIbefore the broker default AMI.internal/cli/coordinator.go:799-831forwards these config values toPOST /v1/leases.Attack Path
Attacker role: authenticated non-admin broker user, including a normal signed user token or shared operator token.
Prerequisites:
Steps:
POST /v1/leasesfor providerawswith caller-chosen values such asawsSGID,awsSubnetID,awsAMI,awsProfile, and attacker-controlledawsSSHCIDRs.fleet.tsbuilds a lease config and only rejects non-admin snapshot sources or dedicated-host pins. The AWS selector fields remain in the config.awsConfiguredSecurityGroupID()returns the request'sawsSGID, soensureSecurityGroup()describes that group and reconciles SSH ingress against the request's source CIDRs.createServer()placesawsProfileintoIamInstanceProfile.Name, placesawsSubnetIDintoNetworkInterface.1.SubnetId, and callsRunInstanceswith the selected AMI.Result: if the broker IAM permits those AWS actions, a non-admin Crabbox caller can make the broker add SSH ingress to a security group the operator did not intend Crabbox to manage, launch instances in a caller-selected subnet, attach a caller-selected instance profile, or boot a caller-selected AMI.
Impact
This gives a non-admin broker user partial control over AWS resources and launch identity that are normally governed by the broker operator. In affected deployments, the user can widen SSH reachability on non-managed security groups or launch broker-paid instances with network placement, image, and instance-profile choices that the broker operator did not approve.
The strongest impact is credential and privilege exposure through an attacker-selected instance profile, because the launched machine can receive AWS role credentials intended for a different workload. Security-group and subnet selection can also expose existing network boundaries or place Crabbox instances into unintended VPC segments. The issue is deployment-dependent: least-privilege broker IAM limited to Crabbox-managed resources reduces or prevents exploitation, but the product currently does not fail closed before making the privileged AWS calls.
Severity Assessment
CVSS Assessment
The v3.1 vector uses high attack complexity because practical exploitation depends on the broker AWS principal having authority over the selected resources. The v4.0 vector records that deployment precondition as
AT:P. The primary risk is confidentiality exposure from attaching an unintended instance profile, with lower integrity and availability effects from unauthorized security-group and placement changes.Recommended Remediation
Fail closed in
createLease()before provider preparation for non-admin AWS resource selectors that can redirect the broker AWS principal:awsSGIDfrom non-admin requests unless it matches an operator-approved broker value.awsSubnetIDfrom non-admin requests unless it matches an operator-approved broker value.awsProfilefrom non-admin requests unless it is in an operator-maintained allowlist.awsAMIfrom non-admin requests unless it is selected through Crabbox's promoted image flow or an operator-maintained allowlist.Add regression coverage in
worker/test/fleet.test.tsfor non-adminPOST /v1/leasesrequests containing each field. Existing tests already prove analogous admin-only behavior forhostID/awsMacHostIDand snapshot-backed lease fields; the new tests should assert the same403 admin_requiredbehavior for these AWS selectors.Validation
Validation method: source review of the latest verification checkout at commit
6dba4afd1c5a4be0a780cf035d1b397e8982d478; no live AWS calls were made.Evidence:
SECURITY.mdsays coordinator authentication, ownership, and sharing controls remain product boundaries, and lists non-admin escalation and destructive provider actions against resources Crabbox cannot strongly identify as its own as in scope.docs/security.mdsays brokered AWS leases otherwise scope SSH ingress to the CLI-detected or request-source CIDR, establishing that the broker owns this security posture for brokered leases.docs/providers/aws.mddocuments the AWS selector fields as configuration, and notes that brokered AWS credentials live in the Worker rather than on developer machines. That means a brokered request uses the coordinator's AWS authority, not the user's local AWS authority.worker/src/fleet.ts:1654-1671contains admin checks for nearby high-risk lease sources and host pins, but no equivalent check forawsSGID,awsSubnetID,awsAMI, orawsProfile.worker/src/config.ts:281-288preserves the caller-supplied AWS fields.worker/src/aws.ts:66-75,1206-1298,1053-1094, and1148-1150show those fields reaching AWS API parameters.internal/cli/coordinator.go:799-831confirms the CLI sends these values in broker lease creation requests.Counterevidence considered:
CRABBOX_AWS_SECURITY_GROUP_IDand managed security group names provide safer defaults when the request omitsawsSGID, butawsConfiguredSecurityGroupID()gives request input priority.