A multi-account AWS attack path playground
58
stars
257
commits
Shell
primary language
Sep 4, 2026
updated
A modular platform for deploying intentionally vulnerable AWS configurations
Quick Start • Lab Catalog • How It Works • Security • Contributing
Pathfinding Labs helps security teams learn how to attack and defend exploitable identity misconfigurations by deploying intentionally vulnerable cloud resources to sandbox environments.
Full lab catalog, individual lab docs, and guided installation: pathfinding.cloud/labs This README is a quick-start guide and command reference for users working directly from the repository.
Not sure how to set this up? See the setup guides — whether you're starting from a single account, already have accounts ready, or want to create a full multi-account AWS org.
Note: Creating your own AWS organization is a great opportunity to learn org level features, like SCPs and IAM Identity Center.
Requires Go 1.25+
go install -v github.com/DataDog/pathfinding-labs/cmd/plabs@latest
brew tap DataDog/pathfinding-labs https://github.com/DataDog/pathfinding-labs
brew install DataDog/pathfinding-labs/plabs
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_64/amd64/')
VERSION=$(curl -fsSL https://api.github.com/repos/DataDog/pathfinding-labs/releases/latest | grep '"tag_name"' | cut -d'"' -f4 | tr -d 'v')
curl -fsSL "https://github.com/DataDog/pathfinding-labs/releases/download/v${VERSION}/plabs_${VERSION}_${OS}_${ARCH}.tar.gz" | tar -xz plabs
sudo mv plabs /usr/local/bin/
git clone https://github.com/DataDog/pathfinding-labs.git
cd pathfinding-labs
go build -o plabs ./cmd/plabs
cp plabs /usr/local/bin/
chmod +x /usr/local/bin/plabs
Downloads terraform, clones repo, runs AWS profile setup wizard
plabs init
plabs
In the TUI: use ↑↓ to browse labs, space to enable/disable labs, a to apply changes (deploy the enabled labs, tear down the disabled labs)
Modular Architecture: Each attack lab is a self-contained, independently deployable module that can be enabled or disabled via plabs.
┌─────────────────────────────────────────────────────────┐
│ 1. Select labs (plabs TUI or plabs enable) │
│ space to toggle in TUI, or: plabs enable <id> │
├─────────────────────────────────────────────────────────┤
│ 2. Deploy (plabs apply) │
│ Creates vulnerable resources in your AWS account │
├─────────────────────────────────────────────────────────┤
│ 3. Test (plabs demo <id>) │
│ Exploit OR detect with your CSPM │
├─────────────────────────────────────────────────────────┤
│ 4. Clean Up (plabs disable <id> && │
│ plabs apply) │
└─────────────────────────────────────────────────────────┘
All labs expose credentials and resource information via grouped Terraform outputs. Demo scripts read these automatically — no manual credential setup needed.
All configuration is managed through plabs. There is no need to edit Terraform files directly.
Run the interactive setup wizard (recommended):
plabs init
Or set values directly (useful for CI/automation):
plabs config set prod-profile my-prod-profile
plabs config set prod-region us-east-1
| Key | Required | Description |
|---|---|---|
prod-profile | Yes | AWS CLI profile for the prod account |
prod-region | Yes | AWS region for the prod account |
dev-profile | No | Dev account profile (cross-account labs only) |
dev-region | No | Dev account region |
ops-profile | No | Ops account profile (cross-account labs only) |
ops-region | No | Ops account region |
You only need ONE AWS account to use most of Pathfinding Labs. All single-account labs deploy to prod. Dev and ops are only required for cross-account labs. See the setup guides if you need help getting accounts and profiles configured.
By default, plabs uses the repository it cloned into ~/.plabs/pathfinding-labs/. If you are contributing and want to test local Terraform changes, enable dev mode from inside the repo:
# Run from inside your cloned pathfinding-labs directory
plabs config set dev-mode true
# plabs now uses local modules instead of ~/.plabs/pathfinding-labs/
plabs config set dev-mode false # revert to the managed copy
Interactive (TUI):
plabs # open the dashboard
# ↑↓ to navigate, space to toggle, a to deploy
CLI:
# Enable by lab ID
plabs enable iam-002-iam-createaccesskey
# Enable multiple at once
plabs enable iam-002-iam-createaccesskey lambda-001-iam-passrole
# Disable
plabs disable iam-002-iam-createaccesskey
plabs apply # shows plan, prompts for confirmation
plabs apply -y # skip confirmation
plabs plan # preview changes without deploying
Each lab includes a demonstration script that shows how to exploit the vulnerability.
Using plabs (recommended):
plabs demo iam-002-iam-createaccesskey
plabs cleanup iam-002-iam-createaccesskey
Directly from the lab directory:
cd modules/scenarios/single-account/privesc-one-hop/to-admin/iam-002-iam-createaccesskey
./demo_attack.sh
./cleanup_attack.sh
The demo scripts provide:
Understanding exactly what Pathfinding Labs creates in your account helps you assess the risk and plan your testing environment appropriately.
Every lab creates IAM principals (users, roles) and policies with deliberate misconfigurations. No existing resources in your account are modified. All created resources use the pl- prefix so they are easy to identify and audit.
Each configured environment gets one dedicated starting user with minimal permissions — this is the simulated attacker's initial foothold:
| User | Environment |
|---|---|
pl-pathfinding-starting-user-prod | Production |
pl-pathfinding-starting-user-dev | Development |
pl-pathfinding-starting-user-operations | Operations |
Starting users are granted only two permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:GetCallerIdentity",
"iam:GetUser"
],
"Resource": "*"
}
]
}
Each environment also includes one admin-level user used exclusively by cleanup scripts to revert demo artifacts:
pl-admin-user-for-cleanup-scriptsThis user has broad permissions. It exists so cleanup scripts can undo changes made during attack demonstrations (e.g., deleting access keys that were created, reverting modified policies). This is another reason to keep your lab environment isolated from production.
Not all labs expose resources to the internet:
| Category | Network Exposure |
|---|---|
| Privilege escalation (all hops) | None — IAM-only, no network resources |
| CSPM Misconfig / Toxic Combo | Some labs intentionally create public S3 buckets, Lambda function URLs, or open security groups |
Each scenario's README documents what it creates and any public-facing resources.
Most labs are IAM-only and incur no AWS charges. Labs that deploy compute or storage resources (EC2, Lambda, ECS) incur small charges while deployed. Recommended: set a billing alert at $10–20/month as a safety net.
Tear down labs when not actively testing:
plabs disable <id> && plabs apply # disable a specific scenario
plabs destroy # destroy all deployed resources
All resources are created only in the accounts and regions you configure via plabs config. Teardown is complete — plabs destroy removes everything Pathfinding Labs created.
All resources follow a consistent naming pattern:
pl-{resource-description}-{context}
Examples:
- pl-pathfinding-starting-user-prod
- pl-cak-admin (CreateAccessKey Admin)
- pl-prod-one-hop-putrolepolicy-role
Globally unique resources (S3 buckets) include a random suffix:
pl-{resource}-{account-id}-{random-6-char}
Example:
- pl-sensitive-data-954976316246-a3f9x2
Pathfinding Labs organizes labs into five categories:
Principal directly modifies itself to gain elevated privileges without traversing to another principal. This is the most direct form of privilege escalation where an entity grants itself additional permissions.
Examples:
Role → iam:PutRolePolicy (on self) → AdminUser → iam:PutUserPolicy (on self) → AdminUser → iam:AddUserToGroup → AdminGroup → AdminRole → iam:AttachRolePolicy (on self) → S3 Bucket AccessSingle principal traversal labs where one principal gains access to another principal's privileges. These are single-account labs within the prod environment.
Examples:
Role → iam:CreateAccessKey → AdminUser → AdminRole → iam:PassRole + lambda:CreateFunction → AdminRole → AdminRole → lambda:UpdateFunctionCode → Lambda with Admin Role → AdminRole → ssm:SendCommand → EC2 with Admin Role → AdminMultiple privilege escalation steps chaining through multiple principals. These are single-account labs within the prod environment.
Examples:
User → sts:AssumeRole → RoleA → iam:CreateAccessKey → UserB → AssumeRole → AdminRoleRoleA → iam:PutRolePolicy → RoleB → AssumeRole → RoleC → Sensitive BucketSingle-condition security misconfigurations that CSPM tools should detect. These are single-account labs within the prod environment.
Examples:
EC2 Instance with Admin Role - Overly permissive instance profileS3 Bucket (public) - Publicly accessible storageSecurity Group (0.0.0.0/0) - Unrestricted network accessMultiple compounding misconfigurations that together create critical security risks. These are single-account labs within the prod environment.
Examples:
Lambda Function (publicly accessible) + Admin RoleEC2 Instance (publicly accessible) + Critical CVE + Admin RoleS3 Bucket (public) + Sensitive Data + No EncryptionPrivilege escalation paths that span multiple AWS accounts (dev, ops, prod). These labs demonstrate how compromise in one account can lead to access in another.
Examples:
Dev:User → AssumeRole → Prod:Role → AdminDev:Role → Lambda:InvokeFunction → Prod:Lambda → Extract Credentials → Prod:AdminOps:User → AssumeRole → Prod:Role → S3:SensitiveBucketpathfinding-labs/
├── modules/
│ ├── environments/ # Base infrastructure (always deployed)
│ │ ├── prod/ # Production environment base resources
│ │ ├── dev/ # Development environment base resources
│ │ └── operations/ # Operations environment base resources
│ │
│ └── scenarios/ # Attack labs (opt-in via flags)
│ ├── single-account/
│ │ ├── privesc-self-escalation/
│ │ │ ├── to-admin/ # Principal modifies itself to gain admin
│ │ │ └── to-bucket/ # Principal modifies itself for S3 access
│ │ ├── privesc-one-hop/
│ │ │ ├── to-admin/ # Single principal traversal to admin
│ │ │ └── to-bucket/ # Single principal traversal to S3 access
│ │ ├── privesc-multi-hop/
│ │ │ ├── to-admin/ # Multiple principal traversals to admin
│ │ │ └── to-bucket/ # Multiple principal traversals to S3 access
│ │ ├── cspm-misconfig/ # Single-condition security misconfigurations
│ │ └── cspm-toxic-combo/ # Multiple compounding misconfigurations
│ ├── tool-testing/ # Edge cases for testing detection engines
│ ├── ctf/ # Capture-the-flag challenges (no demo scripts)
│ ├── attack-simulation/ # Recreations of real-world cloud breaches
│ └── cross-account/
│ ├── dev-to-prod/ # Dev → Prod attack paths
│ │ ├── one-hop/ # Single-hop cross-account escalation
│ │ └── multi-hop/ # Multi-hop cross-account escalation
│ └── ops-to-prod/ # Ops → Prod attack paths
│ └── one-hop/ # Single-hop cross-account escalation
│
├── main.tf # Root module with conditional instantiation
├── variables.tf # Boolean flags for each scenario
├── outputs.tf # Credential outputs for testing
└── terraform.tfvars # Your configuration (gitignored)
Each lab follows a standard structure:
scenario-name/
├── main.tf # Terraform resources
├── variables.tf # Input variables
├── outputs.tf # Output values
├── README.md # Documentation with mermaid diagrams
├── demo_attack.sh # Exploitation demonstration
└── cleanup_attack.sh # Artifact cleanup script
Each lab documents what a properly configured CSPM should detect:
Expected CSPM Alerts:
MITRE ATT&CK Mapping:
We welcome contributions! To add a new scenario:
plabs config set dev-mode true) to use your local copy, then plabs enable <id> && plabs applySee our Contributing Guide for detailed instructions.
This project is licensed under the Apache License 2.0.
Shell
57.7%
HCL
31.9%
Go
8.5%
Python
1.2%
A multi-account AWS attack path playground
58
stars
257
commits
Shell
primary language
Sep 4, 2026
updated
A modular platform for deploying intentionally vulnerable AWS configurations
Quick Start • Lab Catalog • How It Works • Security • Contributing
Pathfinding Labs helps security teams learn how to attack and defend exploitable identity misconfigurations by deploying intentionally vulnerable cloud resources to sandbox environments.
Full lab catalog, individual lab docs, and guided installation: pathfinding.cloud/labs This README is a quick-start guide and command reference for users working directly from the repository.
Not sure how to set this up? See the setup guides — whether you're starting from a single account, already have accounts ready, or want to create a full multi-account AWS org.
Note: Creating your own AWS organization is a great opportunity to learn org level features, like SCPs and IAM Identity Center.
Requires Go 1.25+
go install -v github.com/DataDog/pathfinding-labs/cmd/plabs@latest
brew tap DataDog/pathfinding-labs https://github.com/DataDog/pathfinding-labs
brew install DataDog/pathfinding-labs/plabs
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_64/amd64/')
VERSION=$(curl -fsSL https://api.github.com/repos/DataDog/pathfinding-labs/releases/latest | grep '"tag_name"' | cut -d'"' -f4 | tr -d 'v')
curl -fsSL "https://github.com/DataDog/pathfinding-labs/releases/download/v${VERSION}/plabs_${VERSION}_${OS}_${ARCH}.tar.gz" | tar -xz plabs
sudo mv plabs /usr/local/bin/
git clone https://github.com/DataDog/pathfinding-labs.git
cd pathfinding-labs
go build -o plabs ./cmd/plabs
cp plabs /usr/local/bin/
chmod +x /usr/local/bin/plabs
Downloads terraform, clones repo, runs AWS profile setup wizard
plabs init
plabs
In the TUI: use ↑↓ to browse labs, space to enable/disable labs, a to apply changes (deploy the enabled labs, tear down the disabled labs)
Modular Architecture: Each attack lab is a self-contained, independently deployable module that can be enabled or disabled via plabs.
┌─────────────────────────────────────────────────────────┐
│ 1. Select labs (plabs TUI or plabs enable) │
│ space to toggle in TUI, or: plabs enable <id> │
├─────────────────────────────────────────────────────────┤
│ 2. Deploy (plabs apply) │
│ Creates vulnerable resources in your AWS account │
├─────────────────────────────────────────────────────────┤
│ 3. Test (plabs demo <id>) │
│ Exploit OR detect with your CSPM │
├─────────────────────────────────────────────────────────┤
│ 4. Clean Up (plabs disable <id> && │
│ plabs apply) │
└─────────────────────────────────────────────────────────┘
All labs expose credentials and resource information via grouped Terraform outputs. Demo scripts read these automatically — no manual credential setup needed.
All configuration is managed through plabs. There is no need to edit Terraform files directly.
Run the interactive setup wizard (recommended):
plabs init
Or set values directly (useful for CI/automation):
plabs config set prod-profile my-prod-profile
plabs config set prod-region us-east-1
| Key | Required | Description |
|---|---|---|
prod-profile | Yes | AWS CLI profile for the prod account |
prod-region | Yes | AWS region for the prod account |
dev-profile | No | Dev account profile (cross-account labs only) |
dev-region | No | Dev account region |
ops-profile | No | Ops account profile (cross-account labs only) |
ops-region | No | Ops account region |
You only need ONE AWS account to use most of Pathfinding Labs. All single-account labs deploy to prod. Dev and ops are only required for cross-account labs. See the setup guides if you need help getting accounts and profiles configured.
By default, plabs uses the repository it cloned into ~/.plabs/pathfinding-labs/. If you are contributing and want to test local Terraform changes, enable dev mode from inside the repo:
# Run from inside your cloned pathfinding-labs directory
plabs config set dev-mode true
# plabs now uses local modules instead of ~/.plabs/pathfinding-labs/
plabs config set dev-mode false # revert to the managed copy
Interactive (TUI):
plabs # open the dashboard
# ↑↓ to navigate, space to toggle, a to deploy
CLI:
# Enable by lab ID
plabs enable iam-002-iam-createaccesskey
# Enable multiple at once
plabs enable iam-002-iam-createaccesskey lambda-001-iam-passrole
# Disable
plabs disable iam-002-iam-createaccesskey
plabs apply # shows plan, prompts for confirmation
plabs apply -y # skip confirmation
plabs plan # preview changes without deploying
Each lab includes a demonstration script that shows how to exploit the vulnerability.
Using plabs (recommended):
plabs demo iam-002-iam-createaccesskey
plabs cleanup iam-002-iam-createaccesskey
Directly from the lab directory:
cd modules/scenarios/single-account/privesc-one-hop/to-admin/iam-002-iam-createaccesskey
./demo_attack.sh
./cleanup_attack.sh
The demo scripts provide:
Understanding exactly what Pathfinding Labs creates in your account helps you assess the risk and plan your testing environment appropriately.
Every lab creates IAM principals (users, roles) and policies with deliberate misconfigurations. No existing resources in your account are modified. All created resources use the pl- prefix so they are easy to identify and audit.
Each configured environment gets one dedicated starting user with minimal permissions — this is the simulated attacker's initial foothold:
| User | Environment |
|---|---|
pl-pathfinding-starting-user-prod | Production |
pl-pathfinding-starting-user-dev | Development |
pl-pathfinding-starting-user-operations | Operations |
Starting users are granted only two permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:GetCallerIdentity",
"iam:GetUser"
],
"Resource": "*"
}
]
}
Each environment also includes one admin-level user used exclusively by cleanup scripts to revert demo artifacts:
pl-admin-user-for-cleanup-scriptsThis user has broad permissions. It exists so cleanup scripts can undo changes made during attack demonstrations (e.g., deleting access keys that were created, reverting modified policies). This is another reason to keep your lab environment isolated from production.
Not all labs expose resources to the internet:
| Category | Network Exposure |
|---|---|
| Privilege escalation (all hops) | None — IAM-only, no network resources |
| CSPM Misconfig / Toxic Combo | Some labs intentionally create public S3 buckets, Lambda function URLs, or open security groups |
Each scenario's README documents what it creates and any public-facing resources.
Most labs are IAM-only and incur no AWS charges. Labs that deploy compute or storage resources (EC2, Lambda, ECS) incur small charges while deployed. Recommended: set a billing alert at $10–20/month as a safety net.
Tear down labs when not actively testing:
plabs disable <id> && plabs apply # disable a specific scenario
plabs destroy # destroy all deployed resources
All resources are created only in the accounts and regions you configure via plabs config. Teardown is complete — plabs destroy removes everything Pathfinding Labs created.
All resources follow a consistent naming pattern:
pl-{resource-description}-{context}
Examples:
- pl-pathfinding-starting-user-prod
- pl-cak-admin (CreateAccessKey Admin)
- pl-prod-one-hop-putrolepolicy-role
Globally unique resources (S3 buckets) include a random suffix:
pl-{resource}-{account-id}-{random-6-char}
Example:
- pl-sensitive-data-954976316246-a3f9x2
Pathfinding Labs organizes labs into five categories:
Principal directly modifies itself to gain elevated privileges without traversing to another principal. This is the most direct form of privilege escalation where an entity grants itself additional permissions.
Examples:
Role → iam:PutRolePolicy (on self) → AdminUser → iam:PutUserPolicy (on self) → AdminUser → iam:AddUserToGroup → AdminGroup → AdminRole → iam:AttachRolePolicy (on self) → S3 Bucket AccessSingle principal traversal labs where one principal gains access to another principal's privileges. These are single-account labs within the prod environment.
Examples:
Role → iam:CreateAccessKey → AdminUser → AdminRole → iam:PassRole + lambda:CreateFunction → AdminRole → AdminRole → lambda:UpdateFunctionCode → Lambda with Admin Role → AdminRole → ssm:SendCommand → EC2 with Admin Role → AdminMultiple privilege escalation steps chaining through multiple principals. These are single-account labs within the prod environment.
Examples:
User → sts:AssumeRole → RoleA → iam:CreateAccessKey → UserB → AssumeRole → AdminRoleRoleA → iam:PutRolePolicy → RoleB → AssumeRole → RoleC → Sensitive BucketSingle-condition security misconfigurations that CSPM tools should detect. These are single-account labs within the prod environment.
Examples:
EC2 Instance with Admin Role - Overly permissive instance profileS3 Bucket (public) - Publicly accessible storageSecurity Group (0.0.0.0/0) - Unrestricted network accessMultiple compounding misconfigurations that together create critical security risks. These are single-account labs within the prod environment.
Examples:
Lambda Function (publicly accessible) + Admin RoleEC2 Instance (publicly accessible) + Critical CVE + Admin RoleS3 Bucket (public) + Sensitive Data + No EncryptionPrivilege escalation paths that span multiple AWS accounts (dev, ops, prod). These labs demonstrate how compromise in one account can lead to access in another.
Examples:
Dev:User → AssumeRole → Prod:Role → AdminDev:Role → Lambda:InvokeFunction → Prod:Lambda → Extract Credentials → Prod:AdminOps:User → AssumeRole → Prod:Role → S3:SensitiveBucketpathfinding-labs/
├── modules/
│ ├── environments/ # Base infrastructure (always deployed)
│ │ ├── prod/ # Production environment base resources
│ │ ├── dev/ # Development environment base resources
│ │ └── operations/ # Operations environment base resources
│ │
│ └── scenarios/ # Attack labs (opt-in via flags)
│ ├── single-account/
│ │ ├── privesc-self-escalation/
│ │ │ ├── to-admin/ # Principal modifies itself to gain admin
│ │ │ └── to-bucket/ # Principal modifies itself for S3 access
│ │ ├── privesc-one-hop/
│ │ │ ├── to-admin/ # Single principal traversal to admin
│ │ │ └── to-bucket/ # Single principal traversal to S3 access
│ │ ├── privesc-multi-hop/
│ │ │ ├── to-admin/ # Multiple principal traversals to admin
│ │ │ └── to-bucket/ # Multiple principal traversals to S3 access
│ │ ├── cspm-misconfig/ # Single-condition security misconfigurations
│ │ └── cspm-toxic-combo/ # Multiple compounding misconfigurations
│ ├── tool-testing/ # Edge cases for testing detection engines
│ ├── ctf/ # Capture-the-flag challenges (no demo scripts)
│ ├── attack-simulation/ # Recreations of real-world cloud breaches
│ └── cross-account/
│ ├── dev-to-prod/ # Dev → Prod attack paths
│ │ ├── one-hop/ # Single-hop cross-account escalation
│ │ └── multi-hop/ # Multi-hop cross-account escalation
│ └── ops-to-prod/ # Ops → Prod attack paths
│ └── one-hop/ # Single-hop cross-account escalation
│
├── main.tf # Root module with conditional instantiation
├── variables.tf # Boolean flags for each scenario
├── outputs.tf # Credential outputs for testing
└── terraform.tfvars # Your configuration (gitignored)
Each lab follows a standard structure:
scenario-name/
├── main.tf # Terraform resources
├── variables.tf # Input variables
├── outputs.tf # Output values
├── README.md # Documentation with mermaid diagrams
├── demo_attack.sh # Exploitation demonstration
└── cleanup_attack.sh # Artifact cleanup script
Each lab documents what a properly configured CSPM should detect:
Expected CSPM Alerts:
MITRE ATT&CK Mapping:
We welcome contributions! To add a new scenario:
plabs config set dev-mode true) to use your local copy, then plabs enable <id> && plabs applySee our Contributing Guide for detailed instructions.
This project is licensed under the Apache License 2.0.
Shell
57.7%
HCL
31.9%
Go
8.5%
Python
1.2%