What Is Purple Team? → OWASP Top 10 in the Cloud → Breach Landscape 2020–2025 → Broken Access Control → MFA Fatigue → CI/CD Secrets → SSRF to IMDS → Container Escape → Supply Chain Attacks → Cloud Lateral Movement → Detection Engineering with eBPF → Cloud IR Playbook → Continuous Purple Team Testing
TL;DR
- Continuous purple team testing infrastructure is the practice of running structured attack simulations against your own environment on a quarterly cadence — not as an annual audit, but as an operational discipline
- Detection time drops exercise-over-exercise when the same technique is simulated repeatedly: the same cross-account
AssumeRoletechnique that took 4 hours to detect in Q4 took 8 minutes by Q2 the following year - The toolchain is open source: Atomic Red Team (ATT&CK-mapped) for host-level techniques, Stratus Red Team for cloud-native attack simulations, and custom scripts for what neither covers
- The debrief template — not the tool — is what turns a simulation into a detection improvement; document what fired, what didn’t, and why before closing the exercise
- Mean time to detect (MTTD) per technique is the only metric that tells you whether the program is working
- Frequency of simulation is the independent variable; better tooling and more headcount are not — how often you practice determines how fast you detect
OWASP Mapping: Cross-cutting — this episode validates defenses against every OWASP Top 10 category covered in this series. EP04 (A01 Broken Access Control), EP05 (A07 Auth Failures), EP06 (A08 Software Integrity), EP07 (A10 SSRF), EP08 (A05 Misconfiguration), EP09 (A06 Vulnerable Components), EP10 (A01 lateral movement), EP11 (A09 Monitoring Failures). Continuous purple team testing is how you verify your fixes for all of them actually hold under simulation.
The Big Picture
┌─────────────────────────────────────────────────────────────────────┐
│ QUARTERLY PURPLE TEAM CYCLE │
│ │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ PLAN │───▶│ SIMULATE │───▶│ DETECT │───▶│ DEBRIEF │ │
│ │ │ │ │ │ (or miss)│ │ │ │
│ │ • Scope │ │ Red runs │ │ │ │ What fired? │ │
│ │ • Safety│ │ technique│ │ Blue logs │ │ What didn't?│ │
│ │ • Week 1│ │ • Week 2 │ │ results │ │ • Week 3 │ │
│ └─────────┘ └──────────┘ └──────────┘ └──────┬──────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────┐ ┌──────────┐ │
│ │ FIX │───▶│ REPEAT │◀──── same technique, updated rules │
│ │ │ │ │ │
│ │ • Rules │ │ Does it │ │
│ │ • Config│ │ catch it │ │
│ │ • Week 4│ │ now? │ │
│ └─────────┘ └──────────┘ │
│ │
│ OUTCOME: MTTD drops exercise-over-exercise │
│ When MTTD < 10 min: retire technique, rotate in the next one │
└─────────────────────────────────────────────────────────────────────┘
Continuous purple team testing infrastructure is not a tool you buy or a team you staff. It is a cadence — the same attack path, run repeatedly against your own environment, until detection time drops to a point where the attacker has no useful dwell time.
From EP01 to EP13: The Arc
In EP01, I described a red team engagement where the blue team took 11 days to detect a compromise. The red team used real techniques. The blue team had all the relevant logs. The detection logic just wasn’t tuned to the specific patterns in this specific environment.
That was the same environment, the same attacker playbook, and the same blue team I am about to describe.
Six months later, same scope. Same techniques. The blue team detected in 22 minutes.
Not because they hired anyone new. Not because they switched SIEMs. Not because they bought a new detection product. Because in the intervening six months, they ran four purple team exercises — one per quarter — using the techniques from the first engagement as the test backlog.
Exercise 1: 11 days → 4 hours. Detection rule didn’t exist. Wrote it on the spot during debrief.
Exercise 2: 4 hours → 47 minutes. Rule existed but had a misconfigured threshold that generated false negatives. Fixed during debrief.
Exercise 3: 47 minutes → 38 minutes. Marginal improvement — the technique was becoming well-detected. Rotated in a new technique.
Exercise 4 (new technique): baseline 4+ hours. Same cycle begins.
The number 22 minutes — which is where the original technique sits now — is not a product of better tooling. It is the product of running the simulation four times and fixing the gap found each time.
That is the arc of this series. EP01 defined the practice. EP02 through EP12 gave you the attack backlog. EP13 gives you the program to run them.
Building the Exercise Program
Cadence: The Three Loops
Most organizations treat purple team as an event. An annual penetration test reframed as “collaborative.” One event per year produces one point of data. One point of data is not a trend.
The program that actually moves MTTD operates in three nested loops:
Quarterly exercises — full simulations with red executing and blue observing. Four per year minimum. Each exercise covers one attack path end-to-end, with timestamps, debrief, and detection rule updates. This is the primary loop.
Monthly tabletop drills — no infrastructure required. Two hours. Pull one technique from the backlog, walk through it verbally: “Where would this show up in our logs? What would the CloudTrail event look like? Do we have a rule? What’s the threshold?” No simulation, just shared mental model. Catches drift in detection logic before the quarterly exercise finds it the hard way.
Weekly detection rule reviews — 15-minute async. Run the detection queries that should fire for your most recent exercises. Do they still return results? Rules that worked in October can silently stop working in January when a Terraform apply changes a logging configuration or a GuardDuty region setting drifts. Drift happens without review.
The quarterly exercise is the load-bearing loop. Monthly tabletops and weekly reviews keep it from regressing between exercises.
The Four-Week Exercise Structure
Each quarterly exercise follows the same four-week structure. Deviating from it is how exercises turn into ad hoc sessions with no durable output.
Week 1: Scope Agreement
──────────────────────
□ Which attack path from this series are we testing?
□ Which systems are in scope (account IDs, namespaces, node names)?
□ Circuit breaker: who can call off the exercise and how?
(One named person. A Slack DM or phone call — not a ticket.)
□ Safety controls: are test accounts isolated from prod data paths?
□ Notification: who needs to know this is happening?
(Cloud provider account team if large-scale, internal leadership)
□ Pre-exercise baseline: run detection queries now and record results
Week 2: Red Executes, Blue Observes
────────────────────────────────────
□ Red team runs the technique — with the actual tool and actual commands
□ Blue team is watching the SIEM / CloudTrail / Falco / GuardDuty
in real time during execution
□ Both sides timestamp everything:
[HH:MM] Technique started
[HH:MM] First observable artifact (log entry, network event)
[HH:MM] Alert fired (or: no alert)
[HH:MM] Blue team acknowledged
□ Do NOT wait until the end to compare notes — call out gaps in real time
Week 3: Debrief and Rule Update
────────────────────────────────
□ Walk through the timeline together — not red presenting to blue
□ For each gap: what data existed? why didn't the rule fire?
(Data existed + rule wrong: fix the rule)
(Data existed + rule missing: write the rule)
(Data didn't exist: fix the logging configuration)
□ Write or update detection rules during the debrief — not as a follow-up ticket
□ Update the runbook: what does the analyst do when this alert fires?
□ Commit all rule changes to version control before the debrief ends
Week 4: Re-Run and Verify
──────────────────────────
□ Red runs the same technique again — no changes to the attack
□ Does the updated detection catch it?
□ Record new MTTD
□ If yes: mark technique as covered, add to retirement queue when MTTD < 10 min
□ If no: iterate — another week of rule work, another re-run
□ Set date and technique for next quarter's exercise
The re-run in Week 4 is not optional. A detection rule written during a debrief and never verified against the actual technique may be logically correct and syntactically wrong, or may fire on a slightly different variant. You don’t know until you run the attack again.
The 10-Attack Rotation from This Series
The techniques in this table are the exercise backlog built across EP04–EP12. Run them in order — or reorder based on your current threat model. The MTTD column is blank until you run the exercise and fill it in.
| Quarter | Attack Path | Source Episode | MTTD (Baseline) | MTTD (After Exercise) |
|---|---|---|---|---|
| Q1 2026 | SSRF to EC2 IMDS (IMDSv2 enforcement check) | EP07 | — | — |
| Q2 2026 | MFA fatigue simulation against test account | EP05 | — | — |
| Q3 2026 | Container escape via --privileged pod |
EP08 | — | — |
| Q4 2026 | Cross-account sts:AssumeRole lateral movement |
EP10 | — | — |
| Q1 2027 | CI/CD secrets exposure via environment variable leak | EP06 | — | — |
| Q2 2027 | S3 public access misconfiguration (broken access control) | EP04 | — | — |
| Q3 2027 | Supply chain: unsigned artifact injection into pipeline | EP09 | — | — |
| Q4 2027 | eBPF-visible process anomaly (persistence via cron) | EP11 | — | — |
| Q1 2028 | CloudTrail disable + GuardDuty suppression | EP12 | — | — |
| Q2 2028 | Full path: SSRF → IMDS → AssumeRole → S3 exfil | EP07 + EP10 | — | — |
Fill in the MTTD columns as you run. That table, populated over two years, is your program’s evidence of improvement. It is also what you show an auditor, a CISO, or a board when asked “how do you know your security controls work?”
The Toolchain
Atomic Red Team (ATT&CK-Mapped Host Techniques)
Atomic Red Team is Red Canary’s library of ATT&CK-mapped attack simulations. Each atomic test maps to a specific MITRE technique, lists the required permissions, and runs as a self-contained script. The library covers over 900 techniques across Linux, macOS, and Windows.
pwsh -Command "Install-Module -Name invoke-atomicredteam -Scope CurrentUser -Force"
# Install the Atomics folder (the actual test library)
pwsh -Command "Invoke-Expression (IWR 'https://raw.githubusercontent.com/redcanaryco/invoke-atomicredteam/master/install-atomicredteam.ps1' -UseBasicParsing)"
# List all techniques available for Linux
pwsh -Command "Invoke-AtomicTest All -ShowDetailsBrief -OS linux"
# Inspect a specific technique before running (T1078: Valid Accounts)
pwsh -Command "Invoke-AtomicTest T1078 -ShowDetails"
# Run test #1 for T1078 (shows what commands execute — dry run first)
pwsh -Command "Invoke-AtomicTest T1078 -TestNumbers 1 -CheckPrereqs"
# Execute the test
pwsh -Command "Invoke-AtomicTest T1078 -TestNumbers 1"
# Clean up after the test
pwsh -Command "Invoke-AtomicTest T1078 -TestNumbers 1 -Cleanup"
For the exercises in this series, the most relevant atomic techniques are:
| MITRE Technique | ID | Covers |
|---|---|---|
| Valid Accounts | T1078 | EP05 (credential reuse) |
| Cloud Instance Metadata API | T1552.005 | EP07 (IMDS access) |
| Container Administration Command | T1609 | EP08 (exec into container) |
| Steal Application Access Token | T1528 | EP06 (CI/CD token theft) |
| Account Discovery | T1087.004 | EP04, EP10 (IAM enumeration) |
Stratus Red Team (Cloud-Native Attack Simulations)
Stratus Red Team is DataDog’s cloud-specific attack simulation framework. Unlike Atomic Red Team (which focuses on host techniques), Stratus covers AWS, GCP, Azure, and Kubernetes attack paths using the actual cloud APIs — the same calls an attacker would make.
# Install (requires Go 1.21+)
go install github.com/DataDog/stratus-red-team/v2/cmd/stratus@latest
# Verify
stratus version
# List all available techniques
stratus list
# List AWS-specific techniques only
stratus list --platform aws
# List Kubernetes techniques
stratus list --platform kubernetes
# Get details on a specific technique before running
stratus show aws.credential-access.ec2-get-user-data
The workflow for each Stratus technique is: warm up (provision prerequisites) → detonate (execute the attack) → cleanup (remove artifacts). Never skip cleanup.
# EP07 exercise: SSRF to IMDS credential access simulation
# Warm up (provisions a test EC2 instance)
stratus warmup aws.credential-access.ec2-get-user-data
# Detonate: simulates accessing EC2 user data to extract credentials
stratus detonate aws.credential-access.ec2-get-user-data
# At this point: check CloudTrail for GetUserData events
# Check GuardDuty for credential access findings
# Record whether your detection fired and when
# Cleanup (terminates the test instance)
stratus cleanup aws.credential-access.ec2-get-user-data
# EP10 exercise: cross-account role assumption
stratus warmup aws.lateral-movement.ec2-instance-connect
stratus detonate aws.lateral-movement.ec2-instance-connect
# Detection check: look for AssumeRole events from unexpected principals
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
--start-time $(date -d '1 hour ago' -u +%Y-%m-%dT%H:%M:%SZ) \
--query 'Events[].{Time:EventTime,User:Username,Source:SourceIPAddress}' \
--output table
stratus cleanup aws.lateral-movement.ec2-instance-connect
# EP08 exercise: Kubernetes container escape simulation
stratus warmup k8s.privilege-escalation.privileged-pod
stratus detonate k8s.privilege-escalation.privileged-pod
# Detection check: Falco should fire container_escape_detection
# Check kubectl audit logs for privileged pod creation
kubectl get events --field-selector reason=Created -A | grep -i privileged
stratus cleanup k8s.privilege-escalation.privileged-pod
The full Stratus technique list as of this writing covers 50+ AWS techniques and 10+ Kubernetes techniques. Run stratus list after installing to see what’s current — the library is actively maintained and new techniques are added when new attack patterns emerge in the wild.
Building Custom Simulation Scripts
Atomic Red Team and Stratus don’t cover everything. MFA fatigue in particular requires tooling specific to your identity provider. Build simple, focused scripts for the gaps.
#!/bin/bash
# simulate-mfa-fatigue.sh
# Simulates an MFA fatigue attack by triggering repeated push notifications
# to a test account. Run ONLY against a designated test user — never a real
# employee account. The test account should have MFA enabled but no access
# to any production systems.
#
# Usage: ./simulate-mfa-fatigue.sh <test-user-email> <idp-test-api-endpoint>
# Example: ./simulate-mfa-fatigue.sh [email protected] https://idp.internal/test/push
TEST_USER="${1:[email protected]}"
IDP_ENDPOINT="${2:-}"
PUSH_COUNT=10
PUSH_INTERVAL=30 # seconds between pushes
if [ -z "$IDP_ENDPOINT" ]; then
echo "ERROR: IDP test API endpoint required as second argument"
exit 1
fi
echo "MFA fatigue simulation"
echo "Target user: $TEST_USER"
echo "Push count: $PUSH_COUNT"
echo "Interval: ${PUSH_INTERVAL}s"
echo ""
echo "Blue team: watch for repeated MFA push events in your IdP logs"
echo "Detection signal: >3 push requests to the same user within 5 minutes"
echo ""
START_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
echo "[$(date -u +%H:%M:%S)] Simulation started — timestamp this for your debrief"
for i in $(seq 1 $PUSH_COUNT); do
echo "[$(date -u +%H:%M:%S)] Sending push request $i of $PUSH_COUNT..."
# Trigger push via your IdP's test/simulation API
# Okta example: POST /api/v1/authn/factors/{factorId}/verify
# Replace with your IdP's actual test endpoint
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "$IDP_ENDPOINT" \
-H "Content-Type: application/json" \
-d "{\"username\": \"$TEST_USER\", \"factor\": \"push\", \"simulation\": true}")
echo " Response: HTTP $HTTP_STATUS"
if [ "$i" -lt "$PUSH_COUNT" ]; then
sleep "$PUSH_INTERVAL"
fi
done
END_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
echo ""
echo "[$(date -u +%H:%M:%S)] Simulation complete"
echo "Start: $START_TIME"
echo "End: $END_TIME"
echo ""
echo "Blue team: check IdP logs for push events in this window"
echo "Expected detection: alert on >3 MFA pushes to single user in 5 min"
#!/bin/bash
# simulate-s3-enum.sh
# Simulates the access pattern of an attacker enumerating S3 buckets
# after obtaining IAM credentials. Run in a test AWS account only.
# Purpose: verify CloudTrail ListBuckets and GetBucketAcl events fire
# and that your detection rule catches credential-based enumeration.
echo "[$(date -u +%H:%M:%S)] S3 enumeration simulation starting"
echo "Blue team: watch CloudTrail for ListBuckets from unexpected IAM principal"
# Enumerate buckets
echo "[$(date -u +%H:%M:%S)] ListBuckets..."
aws s3api list-buckets --query 'Buckets[].Name' --output text
# Attempt to read bucket ACLs (generates GetBucketAcl events)
echo "[$(date -u +%H:%M:%S)] Checking ACLs..."
aws s3api list-buckets --query 'Buckets[].Name' --output text | \
tr '\t' '\n' | \
while read -r bucket; do
aws s3api get-bucket-acl --bucket "$bucket" 2>/dev/null | \
jq -r '.Grants[].Grantee | select(.URI != null) | .URI' | \
grep -q "AllUsers" && echo "PUBLIC ACL: $bucket"
done
echo "[$(date -u +%H:%M:%S)] Enumeration complete — check CloudTrail now"
The pattern for custom scripts: timestamp every action, print what the blue team should be watching for, clean up after execution. A simulation script that leaves test resources running is how exercises create incidents instead of preventing them.
Measuring Progress
The metric that matters is MTTD per technique, tracked over time. Everything else — alert count, tool coverage, headcount — is a proxy.
MTTD tracking table: Cross-Account AssumeRole (EP10)
─────────────────────────────────────────────────────
Exercise Date Technique MTTD Notes
─────────────────────────────────────────────────────
Q4 2025 Oct 12 Cross-acct AssumeRole 4 hours No detection rule existed
Q1 2026 Jan 18 Cross-acct AssumeRole 45 min Rule written, threshold wrong
Q2 2026 Apr 5 Cross-acct AssumeRole 8 min Threshold fixed, alert configured
─────────────────────────────────────────────────────
Status: MTTD < 10 min achieved — technique retired from rotation
Next: Rotate in CI/CD secrets exposure (EP06)
When MTTD falls below 10 minutes for a technique, retire it from the quarterly rotation. Add it to a “verified coverage” list. Run it annually to confirm the detection hasn’t regressed. Rotate a new technique from the backlog into the quarterly slot.
Ten minutes is the threshold because below that, an attacker executing this technique in your environment has less dwell time than it takes them to pivot to the next stage. It’s not a hard security boundary — it is a practical operational signal that the technique is well-detected enough to stop driving your exercise cadence.
Track coverage at the series level:
# Create a coverage tracking file
cat > ~/purple-team-coverage.txt << 'EOF'
Technique Episode Status MTTD
──────────────────────────────────────────────────────────────
S3 public access (broken ACL) EP04 Not started —
MFA fatigue EP05 Not started —
CI/CD secrets (env var leak) EP06 Not started —
SSRF to IMDS EP07 Not started —
Container escape (privileged) EP08 Not started —
Supply chain (unsigned build) EP09 Not started —
Cross-account AssumeRole EP10 Not started —
Process anomaly (eBPF-visible) EP11 Not started —
CloudTrail disable EP12 Not started —
Full chain (EP07 + EP10) EP07+10 Not started —
EOF
Update the status column after each exercise. “Not started” → “In rotation” → “MTTD: X min” → “Retired (< 10 min)”. That file, kept in version control, is the program’s durable record.
The Debrief Template
The debrief is where the detection improvement happens. Without structure, debriefs turn into post-mortems that produce action items nobody closes. Use this template — fill it out during the debrief, not after.
# Purple Team Exercise Debrief
Exercise: [name, e.g. "SSRF to IMDS — Q1 2026"]
Date: [YYYY-MM-DD]
Attack path: [from which EP, e.g. "EP07: SSRF to Cloud Metadata"]
Participants: [red team members] / [blue team members]
## Timeline
| Time (UTC) | Event |
|------------|-------|
| HH:MM | Attack started |
| HH:MM | First observable artifact (specify: log entry / network event / process spawn) |
| HH:MM | Alert fired in [tool] — or: no alert |
| HH:MM | Blue team acknowledged |
| HH:MM | Exercise concluded |
MTTD this exercise: [X hours / Y minutes / not detected]
## What Fired
- [Tool]: [Alert name / rule name] — fired at [HH:MM], [latency] after attack started
- [Tool]: [Alert name] — fired at [HH:MM]
## What Should Have Fired and Didn't
- [Expected detection] — root cause: [rule missing / rule wrong / data missing / log not ingested]
- [Expected detection] — root cause: [...]
## Root Cause of Gaps
1. [Gap 1]: [Why the detection didn't exist or didn't work — be specific]
2. [Gap 2]: [...]
## Actions
- [ ] Write detection rule for [gap] — owner: [name] — due: [date]
- [ ] Update runbook [X] to include response steps for [alert] — owner: [name]
- [ ] Fix configuration: [Y] — owner: [name] — due: [date]
- [ ] Commit all rule changes to [repo/path] — owner: [name] — due: today
## Re-Run Result (Week 4)
Date: [YYYY-MM-DD]
MTTD: [X minutes]
Detection: [fired / did not fire]
Notes: [what changed, what's still open]
## Next Exercise
Date: [target quarter start]
Technique: [from backlog]
Source: [EP number]
The most important line in this template is “due: today” for committing rule changes to version control. Detection improvements that live only in the SIEM’s web UI get overwritten by the next infrastructure apply or the next policy sync. They disappear without a trace, and the next exercise finds the same gap again.
Series Closer: What This Series Taught
Looking back across all 13 episodes:
- EP01 — Purple team is a practice, not a team. Red executes, blue observes, both debrief together.
- EP02 — OWASP Top 10 applies to infrastructure. Every category has a cloud-native equivalent.
- EP03 — The 2020–2025 breach landscape is three themes: identity, supply chain, misconfiguration.
- EP04 — Broken access control is the most common failure. IAM wildcards and public S3 buckets are the infrastructure form.
- EP05 — MFA fatigue exploits push-based MFA UX. The fix is hardware keys — not training.
- EP06 — Secrets in CI/CD pipelines are structural, not behavioral. Pre-commit hooks and SAST scanning are the fix.
- EP07 — IMDSv1 has no authentication. Any SSRF anywhere is a straight line to IAM credentials.
- EP08 —
--privilegederases the boundary between container and host. Two commands from compromised pod to root on the node. - EP09 — Supply chain attacks target the trust chain, not the code. XZ Utils was two years of social engineering.
- EP10 — Cloud lateral movement is IAM trust misconfiguration, not network pivoting. One overly broad
sts:AssumeRoletrust policy is enough. - EP11 — eBPF sees what CloudTrail doesn’t — kernel-level process and network events in real time, before the attacker’s process exits.
- EP12 — Incident response quality is inversely proportional to how much you practiced it. The organizations that contain in 4 hours practiced containing in 4 hours.
- EP13 — Frequency of simulation is the variable that changes detection time.
Every attack in this series exploited something that existed before the attacker arrived. The attacker didn’t create the IAM wildcard, the ungated CI/CD pipeline, the privileged pod, or the IMDSv1 endpoint. They found what was already there.
Purple team is how you find it first.
That’s the entire premise. Thirteen episodes to demonstrate it across ten attack paths. The practice is now yours to run.
What’s Next — Cross-Series
The Purple Team Playbook ends here, but the technical depth that makes it work lives in three other series running in parallel on linuxcent.com:
Kernel-level detection — the eBPF: From Kernel to Cloud series covers everything from kernel hooks and BPF maps to Cilium and runtime security with Tetragon. EP11 in this series referenced eBPF detection; the eBPF series is where the implementation depth lives.
Hardened base images — closing the OS-level attack surface that EP08 and EP09 in this series exploited starts at image build time. The hardened image pipeline gate post covers building signed, minimal base images that eliminate entire attack surface categories before the container ever starts.
The identity layer — every attack in this series ultimately had an IAM component: the overly permissive role, the wildcard policy, the cross-account trust boundary that was too broad. What Is Cloud IAM starts the 12-episode Cloud IAM series that maps the identity architecture underpinning all of it.
These series are designed to be read in parallel — techniques that appear as one-line references in this series get full treatment in the others. The eBPF series covers TC hooks and bpftrace in the depth that EP11 introduced. The IAM series covers sts:AssumeRole trust policies in the depth that EP10 referenced.
Get notified when the next series starts → linuxcent.com/subscribe
⚠ Production Gotchas
Test account isolation is not optional. Every simulation in this series should run in a dedicated AWS account (or GCP project / Azure subscription) with no trust relationships to production accounts. One stratus detonate command that runs in a prod account and modifies IAM trust policies is an incident, not an exercise. The cost of a test account is zero compared to the cost of a real incident.
Stratus leaves state. If you interrupt a stratus detonate run, the warmup infrastructure is still running and costing you money. Always run stratus cleanup even after an interrupted exercise. Add it to a trap in your exercise runbook.
Detection rules written during debriefs may use syntax your SIEM doesn’t support. Rule logic written in a 30-minute debrief window gets reviewed quickly. Run each new rule against 30 days of historical logs before relying on it. A rule that has never matched against known-bad historical data may have a quiet logic error.
Alerting ≠ detection. A rule that fires but routes to a queue no one monitors is not a detection. The debrief template asks “alert fired in [tool]” — confirm the alert also appeared in a queue that an on-call engineer would have seen. Route validation is part of the exercise.
Scope creep kills exercises. The first quarter an exercise runs long, someone proposes “let’s just add two more techniques since we have time.” Don’t. Four well-documented techniques with full debrief and verified re-runs beat ten half-documented techniques with action items that never close. Keep the scope tight. Add techniques by rotating them into the next quarter’s slot.
Quick Reference
| Component | What It Is | When to Use |
|---|---|---|
| Atomic Red Team | ATT&CK-mapped host technique library | Host-level techniques: process execution, credential access, persistence |
| Stratus Red Team | Cloud-native attack simulations | AWS/GCP/Azure/K8s API-based attack paths |
| Custom scripts | Org-specific simulations | MFA fatigue, IdP-specific attacks, internal tool abuse |
| MTTD | Mean time to detect — measured per technique | Primary metric; track over time per technique |
| Circuit breaker | Named person who can halt an exercise | Safety control; must be identified in Week 1 |
| Debrief template | Structured post-exercise documentation | Filled during debrief, committed to version control same day |
| Retirement threshold | MTTD < 10 minutes | When to rotate a technique out of quarterly rotation |
| Coverage list | Techniques with verified detections | Auditable record of what your program has validated |
Key Takeaways
- Continuous purple team testing infrastructure means running the same attack paths quarterly — not annually — until MTTD per technique drops below 10 minutes
- The four-week exercise structure (scope → simulate → debrief → re-run) is the unit of work; deviating from it is how exercises produce action items instead of detection improvements
- Atomic Red Team covers ATT&CK-mapped host techniques; Stratus Red Team covers cloud-native attack simulations; custom scripts cover what neither does
- The debrief template — filled in during the session, committed to version control before the session ends — is what separates exercises that improve detection from exercises that produce unread reports
- MTTD < 10 minutes for a technique means retire it and rotate in the next one from the backlog this series gave you
- The frequency of simulation is the variable that changes detection time. Not the tools. Not the headcount. How often you practice.