Rehearse real cloud attacks safely — in your own AWS account, before attackers do.
MayaTrail connects to your AWS account, provisions a realistic, intentionally vulnerable environment, runs a real adversary emulation against it, and shows you exactly what an attacker could reach — then tears it all down automatically. Every emulation ships with MITRE ATT&CK mappings and ready-to-deploy detection rules.
Cloud and Kubernetes misconfiguration is the leading cause of modern breaches — a single over-permissive IAM role, an EC2 instance with IMDSv1 enabled, or a pod with a writable hostPath mount is enough to lose an account or a cluster. Yet security teams have almost no safe way to rehearse these attacks against infrastructure that looks like their own:
Production is too risky to attack. You can't run a credential-theft-to-persistence chain, or a pod-to-node escape, against live infrastructure just to see if it works. Pentests are expensive and infrequent. A point-in-time engagement once or twice a year doesn't keep pace with infrastructure that changes daily. Knowing about a misconfiguration isn't the same as knowing your blast radius. Most tools flag that IMDSv1 is on or that a pod can mount hostPath; they don't show you the full kill chain it unlocks — or whether your detections would catch it. The result: teams discover whether their cloud or cluster is exploitable only when a real attacker shows them.
MayaTrail closes the loop — connect → deploy → attack → observe → auto-destroy — running real adversary emulations inside an isolated, disposable environment in your own AWS account.
- Connect your AWS account by granting a scoped, cross-account IAM role (no long-lived keys to hand over — MayaTrail assumes the role via STS at run time), or target a MayaTrail-provisioned Kubernetes host for cluster-level emulations.
- Deploy a realistic, intentionally vulnerable environment from code (Pulumi).
- Attack it with a real adversary emulation modelled on a documented campaign or a known CVE/misconfiguration class.
- Observe the outcome in a dashboard: the kill chain, MITRE ATT&CK coverage, blast radius, and an immutable audit log — plus detection rules you can take straight to your SIEM.
- Auto-destroy — every environment has a TTL, so nothing lingers and costs stay bounded.
Spin it up, run the breach, learn from it, and let it clean itself up. Repeat as often as your infrastructure changes.
MayaTrail is built for the people responsible for cloud and cluster security posture:
| Persona | What they get from MayaTrail |
|---|---|
| Detection Engineer | Real attacker telemetry plus shipped Sigma + KQL rules to validate and tune detections against. |
| Security Engineer | A safe range to validate whether a misconfiguration is actually exploitable end-to-end. |
| Cloud Security Engineer | Realistic, documented attack scenarios run safely inside their own AWS account. |
| Platform / Kubernetes Engineer | Hands-on proof of cluster-level attack paths without touching production clusters. |
| DevSecOps Engineer | Disposable, IaC-defined environments that fit into existing pipelines. |
| SOC Analyst | A controlled environment to study real attack patterns and response. |
| Security Architect | Evidence of blast radius to inform guardrails and policy decisions. |
- Multi-platform — AWS today, with native Kubernetes attack emulations and the plugin model built to extend to Azure and GCP.
- Runs against your own infrastructure — AWS connection is via a scoped, cross-account IAM role that MayaTrail assumes at run time; no long-lived credentials are stored.
- Real-world adversary emulations — modelled on documented campaigns, not toy scenarios.
- Mapped to MITRE ATT&CK — every phase is tied to a technique, with coverage surfaced on the dashboard.
- Ships detection rules — each emulation includes Sigma and KQL rules and an incident-response playbook, ready for your SIEM.
- Ephemeral and cost-aware — environments carry a TTL and are auto-destroyed on a schedule; cost estimates are shown up front.
- Plugin-based emulation packages — drop in a new emulation package and it's auto-discovered, infra and detections included.
- Auditable — an immutable log records every connect, deploy, attack, and destroy.
Cloud and Kubernetes footprints are growing faster than the teams defending them, and the discipline is shifting from point-in-time pentests toward continuous threat exposure management — always knowing whether your environment is exploitable today, not last quarter. MayaTrail makes that rehearsal loop cheap, safe, and repeatable enough to run continuously.
step1 is the first phase of a deliberately staged platform. Direction ahead:
- A growing library of adversary emulations across more documented campaigns
- Deeper Kubernetes coverage: multi-node clusters, managed control planes (EKS/GKE/AKS), and container-runtime-level attack paths
- Multi-cloud support (Azure, GCP, Kubernetes) — the platform model already accounts for it
- Deeper detection-engineering workflows built on emulation telemetry
- CI/CD integration to rehearse attacks on every infrastructure change
The sections below are technical reference for running and contributing to MayaTrail.
MayaTrail runs as a full-stack web application. The flow for a single emulation:
- Connect — for AWS emulations, a user grants a cross-account IAM role scoped to the permissions each emulation needs; the connectors app verifies it and MayaTrail assumes it via STS at run time (no long-lived keys are stored). Kubernetes emulations target a MayaTrail-provisioned host running a lightweight, isolated control plane.
- Deploy — the enterprise Celery worker provisions the emulation's infrastructure into the user's account using the Pulumi Automation API, in-process (no Docker socket, no ephemeral Pulumi containers). Pulumi state lives in a dedicated S3 state bucket.
- Attack — the emulation package's
attack.pyexecutes the kill chain against the freshly provisioned infrastructure. - Observe — results, MITRE ATT&CK mappings, and detection rules surface in the dashboard;
the
logsapp records an immutable audit trail. - Auto-destroy — each stack carries a TTL (SCARLETEEL defaults to 4 hours, most Kubernetes emulations default to 2 hours); Celery Beat runs an auto-destroy task every 15 minutes so expired environments are cleaned up and costs stay bounded.
AWS emulations run against your own account via a cross-account IAM role — MayaTrail never asks for or stores long-lived AWS access keys. To connect:
- Create an IAM role in your AWS account (e.g.
MayaTrailRole). - Attach a trust policy allowing the MayaTrail platform account to assume it (see below).
- Attach a permissions policy scoped to what emulations need — the connector page in the app shows the exact policy required, grouped by emulation category, plus the full JSON to copy/paste.
- Submit the role's ARN on the connector page
(
arn:aws:iam::<your-account-id>:role/<role-name>). MayaTrail verifies it live viasts:AssumeRolebefore marking the connection verified — nothing is provisioned until you actually run an emulation.
If you're using the hosted instance at app.mayatrail.tech, trust
MayaTrail's platform AWS account, 940482414561, in your role's trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::940482414561:root" },
"Action": "sts:AssumeRole"
}
]
}If you're running your own instance (see Quick start below), the
trust policy must instead reference your own platform account — the AWS account behind the
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY credentials configured in backend/.env, since
that's the identity the connectors app assumes the role as.
# 1. Configure environment
cp backend/.env.example backend/.env
# Fill in SECRET_KEY, AWS credentials, and STATE_BUCKET in backend/.env
# 2. Start the full stack
docker-compose up --buildThe application is available at http://localhost. Migrations run automatically on backend
startup.
Prerequisites: Docker and Docker Compose, plus AWS credentials for the platform account (used to AssumeRole into target accounts, provision Kubernetes hosts, and store Pulumi state).
| Variable | Description |
|---|---|
SECRET_KEY |
Django secret key |
DATABASE_URL |
PostgreSQL connection string |
REDIS_URL |
Celery broker + result backend |
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY |
Platform AWS credentials (STS AssumeRole + state bucket) |
AWS_DEFAULT_REGION |
Default AWS region (e.g. ap-south-1) |
STATE_BUCKET |
S3 bucket for Pulumi state (e.g. mayatrail-state-bucket) |
PULUMI_CONFIG_PASSPHRASE |
Passphrase for Pulumi stack secrets |
EMULATIONS_BASE_DIR |
Where emulation packages are mounted (/opt/emulations) |
REGISTRATION_INVITE_CODE |
Invite code gating self-registration |
GOOGLE_CLIENT_ID |
Google SSO client ID |
cd frontend/UI
npm install
npm run dev # Vite dev server on http://localhost:3000The point of MayaTrail isn't the module list — it's letting your team run a real APT chain end-to-end and find out, concretely, whether your detections fire, your SOC catches it in time, and your playbooks and guardrails hold up under an actual (contained) compromise. Use it to:
-
Test detections — run the real technique and confirm your Sigma/KQL rules actually fire, not just that they parse.
-
Grade SOC response — trigger a live-looking incident and time how fast the team detects, triages, and escalates.
-
Validate playbooks — walk the shipped incident-response playbook against a real, contained compromise instead of a tabletop hypothetical.
-
Prove guardrails — confirm IAM boundaries, network policies, and Kubernetes admission controls actually stop the attack where you think they do.
-
Run drills on demand — spin up a fresh, disposable environment for a red/blue/purple team exercise whenever you need one, then let it auto-destroy. Each emulation packages a documented threat-actor campaign or a disclosed CVE/misconfiguration class as a self-contained, auto-discovered plugin: Pulumi infra to stand up the vulnerable environment, an attack script that executes the real kill chain, MITRE ATT&CK mappings per phase, Sigma/KQL detection rules, and an incident-response playbook. Today, it spans multi-phase AWS campaigns (including SCARLETEEL, AMBERSQUID, Codefinger, and DangerDev), a library of narrower single-technique AWS emulations for isolating one detection at a time, and Kubernetes emulations covering RBAC abuse, adversary-in-the-middle, Pod Security Admission bypass, and host escape. The full, current catalogue — MITRE coverage, severity, cost and TTL per module — is browsable live in the dashboard, since new packages are auto-discovered as soon as they land in emulations/
-
MANIFEST.py— identity, kill-chain phases, MITRE ATT&CK mappings, cost and TTL metadata -
attack.py— arun(outputs)function that executes the kill chain -
infra/— a Pulumi program that provisions the vulnerable environment -
detections/— Sigma and KQL detection rules, one set per technique -
PLAYBOOK.md— an incident-response playbook for the campaign
Important
Writing or migrating an emulation? Start with the authoring knowledge base.
The authoring guide, the copy-paste package template, and the per-emulation migration records live in a
private submodule at emulations/_kb/ (repo MayaTrail/emulations-authoring — access required). It is the
source of truth for the contracts every emulation must satisfy (MANIFEST/dashboard, readiness, naming,
secrets), the validation gates, and the gotchas — follow it and a new package "lights up" the platform with
no backend changes.
git submodule update --init emulations/_kb # populate it (needs access to the private repo)
# then read emulations/_kb/AUTHORING.md
# start new cp -r emulations/_kb/_TEMPLATE emulations/<name>
# migration emulations/_kb/migrations/<name>.md (from MIGRATION_TEMPLATE.md)Without submodule access emulations/_kb/ stays empty — the public emulation packages still build and run;
only the authoring methodology is gated.
The full platform runs as a Docker Compose stack with 7 services:
| Service | Purpose |
|---|---|
db |
PostgreSQL 16 database |
redis |
Celery message broker + result backend |
backend |
Django REST API (Gunicorn) |
worker_enterprise |
Celery worker — deploys, attacks, and destroys emulations in the user's AWS account via STS AssumeRole (Pulumi Automation API, in-process) |
beat |
Celery Beat scheduler — auto-destroys expired stacks every 15 minutes |
ui |
React SPA (Nginx, non-root) |
nginx |
Edge reverse proxy (routes / to UI, /api/ + /admin/ to backend) |
step1/
├── backend/ # Django REST API
│ ├── apps/
│ │ ├── users/ # Auth: registration (invite code), JWT login, Google SSO, profile
│ │ ├── connectors/ # AWS account connection via cross-account IAM role
│ │ ├── emulations/ # Emulation catalogue + run lifecycle (deploy/attack/destroy)
│ │ ├── infrastructure/ # Stack model, Celery tasks, TTL auto-destroy
│ │ ├── metrics/ # Platform Overview dashboard metrics (MITRE + attack-surface coverage)
│ │ └── logs/ # Read-only audit log
│ ├── config/ # Django settings (base/dev/prod), Celery, URLs
│ ├── Dockerfile # Backend / beat image
│ ├── Dockerfile.worker # Enterprise worker image
│ └── requirements.txt
├── emulations/ # Adversary emulation packages (mounted at /opt/emulations)
│ ├── registry.py # Auto-discovers packages via MANIFEST.py
│ ├── scarleteel/ # SCARLETEEL 2.0 campaign emulation
│ ├── ambersquid/ # AMBERSQUID campaign emulation
│ ├── codefinger/ # Codefinger S3 ransomware campaign emulation
│ ├── dangerdev/ # DangerDev campaign emulation
│ ├── aws_*/ # ~30 single-technique atomic AWS emulations based on stratus red team's emulations
│ ├── k8s_rbac_impersonation/ # K8s RBAC impersonation privilege escalation
│ ├── k8s_external_ips_mitm/ # K8s CVE-2020-8554 externalIPs MITM
│ ├── k8s_pod_status_mitm/ # K8s pod status.podIP MITM
│ ├── k8s_pvc_psa_bypass/ # K8s Pod Security Admission bypass via PV abuse
│ ├── k8s_writable_log_escape/ # K8s writable /var/log host escape
│ └── k8s_attack_readme.md # Kubernetes emulation catalogue walkthrough
│ # each package: MANIFEST.py, attack.py, infra/ (Pulumi), detections/, PLAYBOOK.md
├── frontend/UI/ # React + TypeScript SPA
│ ├── src/
│ │ ├── components/ # dashboard, emulations, playbooks, detections, platforms, ...
│ │ ├── context/ # Auth, Theme, Platform contexts
│ │ ├── services/ # API service layer (Axios)
│ │ ├── data/ # Static taxonomies (e.g. attack-surface mapping)
│ │ └── types/ # TypeScript type definitions
│ ├── DESIGN.md # Frontend design system (source of truth)
│ └── Dockerfile # Multi-stage: Node build -> Nginx
├── docker-compose.yml # Full stack orchestration (7 services)
└── nginx.conf # Edge reverse proxy configGood entry points for understanding the codebase:
docker-compose.yml— the full service topology and how the pieces connectemulations/scarleteel/— a complete AWS emulation package (manifest, attack, infra, detections, playbook)emulations/k8s_rbac_impersonation/— a complete Kubernetes emulation package, andemulations/k8s_attack_readme.mdfor how all five Kubernetes attacks work end to endemulations/_kb/AUTHORING.md— the authoring/migration knowledge base (private submodule); read it before writing or migrating an emulation (see the Emulations callout to initialise it)frontend/UI/DESIGN.md— the frontend design system; read it before any UI change
Adding or migrating an emulation is the most common contribution. Read emulations/_kb/AUTHORING.md first,
then copy emulations/_kb/_TEMPLATE/ to a new emulations/<name>/, fill in the MANIFEST.py and an attack.py
exposing run(outputs, region) — the registry discovers it automatically — and record the work in
emulations/_kb/migrations/<name>.md. The KB defines the contracts CI enforces, so following it keeps your
package from failing the build.
Safety note: MayaTrail provisions intentionally vulnerable AWS resources inside the connected account. Use only a dedicated, isolated test account. Environments auto-destroy on their TTL, and you can also tear them down on demand from the dashboard.

