Security Hardening
Security hardening best practices for AWS BYOC stacks
Security Model
WarpBuild BYOC on AWS is designed with workload isolation at its core:
- Ephemeral instances: Each CI job runs on a distinct, freshly provisioned EC2 instance that is terminated after the job completes. There is no shared state or cross-contamination between jobs.
- User-controlled permissions: The permissions available to runner instances are exactly what you choose to provide via security groups and IAM roles/instance profiles. WarpBuild does not inject additional permissions into runner workloads.
The WarpBuild stack (created via CloudFormation) provisions networking infrastructure (VPC, subnets, security groups, VPC endpoints) and an S3 bucket. All IAM permissions for runner workloads are managed independently by you through instance profiles.
Current Stack Security Posture
The default CloudFormation stack creates:
| Resource | Default Configuration |
|---|---|
| Security Group | All egress allowed (0.0.0.0/0); ingress allowed from VPC subnet CIDRs only |
| VPC Endpoints | S3 (gateway), ECR API and ECR Docker (image pulls) as interface endpoints - traffic stays within AWS network |
| S3 Bucket | Used for WarpBuild cache data |
| Subnets | Public subnets with optional private subnets + NAT gateways for static egress IPs |
| Network ACLs | Default VPC NACLs (allow all) - customize these for additional controls |
The security group attached to runner instances is defined at the stack level. In create mode, the security group is provisioned automatically by the CloudFormation template. In import mode, you select an existing security group when creating the stack.
Best Practices for Tighter Controls
1. Use a dedicated VPC or AWS account
Isolate your CI workloads from production infrastructure by deploying the WarpBuild stack in:
- A separate VPC within the same account, or
- A completely separate AWS account dedicated to CI/CD
This limits the blast radius if a runner is compromised and simplifies audit boundaries. Use AWS Organizations to manage cross-account access where needed.
2. Block all inbound connections
CI runners do not need to accept inbound connections - not even from within the VPC. The default WarpBuild security group allows ingress from VPC subnet CIDRs, but for tighter controls you should block all inbound traffic entirely:
- Remove all inbound rules from the runner security group.
- Do not attach security groups that allow
0.0.0.0/0or VPC CIDR inbound. - If using import mode, create a security group with no inbound rules:
{
"InboundRules": [],
"OutboundRules": [
{
"IpProtocol": "-1",
"Destination": "0.0.0.0/0",
"Description": "Allow all outbound"
}
]
}VPC endpoints (S3, ECR) will continue to function with outbound-only rules since runners initiate the connections.
3. Disallow inter-instance communication
Runner instances do not need to communicate with each other. To prevent lateral movement:
- Use Network ACLs on your subnets to deny traffic between instances within the same subnet. Since each runner gets a unique IP, you can use NACLs to restrict intra-subnet traffic while still allowing traffic to VPC endpoints and NAT gateways.
- Alternatively, create a more restrictive security group that only allows egress to
0.0.0.0/0and ingress exclusively from VPC endpoint ENIs (rather than the full subnet CIDR).
Refer to AWS Network ACLs documentation for configuration details.
4. Restrict outbound traffic
While runners need outbound internet access, you can tighten egress rules. The following outbound access is required for runners to function:
api.warpbuild.com- WarpBuild control plane (runner registration and lifecycle)api.github.com,github.com- GitHub API and Git operations
S3 access for cache is routed through the S3 VPC gateway endpoint provisioned by the stack. Runner telemetry requires outbound HTTPS access to Warpbuild AWS S3.
Additionally, allow access to any package manager registries or external services your builds depend on.
5. Attach least-privilege instance profiles
Instance profiles define what AWS resources your runner workloads can access. Attach an instance profile with only the permissions your CI jobs need.
Setting up an instance profile
An instance profile is configured at the runner level in the WarpBuild dashboard (Custom Runner configuration > Instance Profile ARN). Each runner can have its own instance profile, allowing you to scope permissions per workload type.
Example: Least-privilege policy for ECR push
If your CI jobs only need to push images to a specific ECR repository:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource": "arn:aws:ecr:<region>:<account-id>:repository/<your-repo>"
}
]
}Example: Least-privilege policy for S3 artifact upload
If your CI jobs need to upload artifacts to a specific S3 bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::<your-artifacts-bucket>",
"arn:aws:s3:::<your-artifacts-bucket>/*"
]
}
]
}Creating the instance profile
- Create an IAM role with the desired policy:
aws iam create-role \
--role-name ci-runner-role \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}
]
}'- Attach your least-privilege policy to the role:
aws iam put-role-policy \
--role-name ci-runner-role \
--policy-name ci-runner-policy \
--policy-document file://policy.json- Create the instance profile and add the role:
aws iam create-instance-profile \
--instance-profile-name ci-runner-profile
aws iam add-role-to-instance-profile \
--instance-profile-name ci-runner-profile \
--role-name ci-runner-role- Grant
iam:PassRoleto the WarpBuild connection role (see Instance Profile setup for details):
aws iam put-role-policy \
--role-name <warpbuild-role-name> \
--policy-name PassRolePolicy \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::<account-id>:role/ci-runner-role",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ec2.amazonaws.com"
}
}
}
]
}'For more details, refer to:
6. Enable IMDSv2
Require Instance Metadata Service Version 2 (IMDSv2) to protect against SSRF attacks that attempt to steal instance credentials. This can be enabled per-runner in the WarpBuild dashboard (Runner Specs > Require IMDSv2).
See IMDS configuration for setup instructions.
Security Checklist
Use this checklist to verify your BYOC AWS stack follows security best practices:
- Stack deployed in a dedicated VPC or AWS account
- Security group blocks all inbound traffic (except VPC endpoint connectivity)
- No security group rules allowing
0.0.0.0/0inbound - Inter-instance communication disabled via NACLs or security group rules
- Outbound traffic restricted to required destinations
- Instance profile attached with least-privilege permissions
- IMDSv2 required on all runners
- S3 bucket lifecycle policies configured for cache expiry
- VPC endpoint policies scoped to required resources
- Tags configured for cost attribution and access control (
managed-by: warpbuild)
Last updated on