Safe Penetration Testing Labs · beginner · ~8 min
- Explain what a **rules-of-engagement (RoE)** document is and why it is signed *before* any testing - List the sections every RoE must contain (scope, out-of-scope, methods, timing, data handling, contacts) - Describe **deconfliction** and an **emergency stop** procedure - Write a clear, specific RoE for a small local lab scenario - Recognize when an action has drifted **out of scope** and what to do about it
A rules-of-engagement (RoE) document is the written agreement between a tester and the owner of the systems being tested. It converts the abstract idea from the previous lesson — "only test with permission" — into a concrete, signed contract that says exactly what you may do, to what, when, and how.
This lesson builds directly on What is ethical hacking?. There, authorization was the principle; here it becomes a document you can actually work from. The RoE is your authorization to act: if it isn't in the RoE, you don't do it.
Think of the RoE as the scope of a trust boundary drawn on paper — everything inside is allowed, everything outside is off-limits by default.
The RoE protects both sides. It protects the owner from surprises (a test that takes a system down at peak hours) and protects you by proving, in writing, that what you did was authorized. In a dispute, the RoE is the evidence that you stayed inside the lines.
It also makes the work professional and repeatable: a good RoE removes ambiguity, so you spend your time testing instead of wondering whether you're allowed to. Every real engagement — and every bug-bounty program's rules page — is a form of RoE.
A complete RoE answers "who, what, when, how, and what-if":
| Section | What it pins down |
|---|---|
| Scope | Exact in-scope targets: IPs, hostnames, apps, accounts, URLs |
| Out-of-scope | Anything not listed — stated explicitly so it's unambiguous |
| Allowed methods | Which techniques are permitted (and which are forbidden, e.g. denial-of-service, social engineering) |
| Timing | The approved testing window(s), including timezone |
| Data handling | What you may access, what you must not keep, how to store/delete evidence |
| Contacts | Who to notify, and an emergency contact reachable during testing |
| Stop procedure | How to halt immediately and who decides |
Pitfall: a vague scope like "the website" invites trouble. List the exact hostnames and note whether subdomains are included.
The safest reading of any RoE is default-deny: if an action, target, or technique is not explicitly allowed, treat it as forbidden. This mirrors secure system design, where you allow known-good and reject everything else.
Deconfliction means coordinating with the owner's defenders so your test traffic isn't mistaken for a real attack (or vice-versa). The RoE names a point of contact and a way to confirm "that alert was us."
An emergency stop is a pre-agreed signal and procedure to halt all testing instantly — used if a system looks fragile, real users are affected, or something unexpected happens.
Scope drift is when testing gradually wanders toward things that were never authorized (a linked subdomain, a third-party service). The moment you notice you're outside the listed scope, stop and check the RoE or ask.
In-scope target --(a link/redirect)--> Unlisted host
allowed OUT OF SCOPE — stop
Knowledge check:
There is no code syntax here — the "syntax" is the structure of the document. A minimal RoE skeleton:
RULES OF ENGAGEMENT
1. Parties + date + signatures
2. In-scope targets (exact)
3. Out-of-scope (explicit)
4. Allowed / forbidden methods
5. Testing window (with timezone)
6. Data handling + evidence rules
7. Points of contact + emergency stop
8. Reporting + retest expectations
Every section should be specific enough that a stranger reading it knows exactly what is and isn't allowed.
A rules of engagement (RoE) document is a written agreement between a penetration tester and the organization being tested. It sets the boundaries for the work.
The RoE is signed before any testing begins. It is your authorization to act.
A complete RoE defines the following:
Without a signed RoE, don't push buttons.
No authorization means no testing. Acting outside the agreed scope can be illegal, even with good intentions.
A filled-in RoE for a fictional local lab — the kind you can safely practice writing:
RULES OF ENGAGEMENT — "Toy Shop" local lab
Date: 2026-07-02 Tester: <your name> Owner: <you>
IN SCOPE
- http://127.0.0.1:8080 (the toy web app, running in a local container)
- The lab database at 127.0.0.1:5432 (test data only)
OUT OF SCOPE
- Any host that is not 127.0.0.1 / localhost
- The host laptop's OS, other containers, and the home network
ALLOWED METHODS
- Manual request inspection, input fuzzing, source-code review
FORBIDDEN
- Any denial-of-service test; any action that deletes real data
TESTING WINDOW
- Any time (single-user local lab)
DATA HANDLING
- Test data only; no real personal data exists in this lab
- Evidence: screenshots + saved requests, deleted when the lab is torn down
CONTACT / STOP
- Single operator; "stop" = shut down the container (docker stop toyshop)
Why it's safe. Every target is loopback (127.0.0.1), so nothing can reach another machine. The out-of-scope section makes the boundary explicit, and the stop procedure is one command.
Reading the sample RoE the way you'd apply it during testing:
| RoE line | It tells you… | If you're unsure |
|---|---|---|
In-scope 127.0.0.1:8080 |
The only app you may test | Anything else → out of scope |
| Out-of-scope "not 127.0.0.1" | The home network is off-limits | Never send traffic off the box |
| Forbidden "no DoS / no deletes" | Some tests can harm even your own lab | Skip destructive tests |
| Window "any time" | Timing constraint (here, none) | On real jobs, test only in-window |
| Data "test data only" | Nothing real is at risk | Still keep minimal evidence |
Stop = docker stop toyshop |
The instant off-switch | Use it the moment something's wrong |
The habit: before each action, ask "is this target and this method listed as allowed?" If not, don't.
Mistake 1 — vague scope.
Wrong: "Scope: the company's website."
Why wrong: is api.company.com included? A staging box? You can't tell.
Fix: list exact hostnames/IPs and state whether subdomains count.
Mistake 2 — testing outside the window. Wrong: running scans at 2 a.m. because it's convenient. Why wrong: outside the approved window, you're unauthorized again — and may trip incident response. Fix: test only during the agreed window; if you need more time, amend the RoE.
Mistake 3 — no stop procedure. Wrong: no agreed way to halt. Why wrong: when a system wobbles, seconds matter and nobody knows who to call. Fix: every RoE names a contact and a one-step stop.
Recognize it: if you can't answer "exactly which targets, exactly when, and how do I stop," the RoE isn't finished.
Applying an RoE is mostly about resolving ambiguity safely:
Questions to ask: Is this exact target listed? Is this method allowed? Am I inside the window? Do I know how to stop right now?
Security & safety — evidence and records. The RoE's data-handling section is a safety control:
A tidy, minimal evidence trail is both more professional and less risky than hoarding data.
Professional habits: never start without a signed RoE; re-read the scope before each session; amend the RoE in writing rather than "just this once" exceeding it. Advanced habits: pre-plan deconfliction with the blue team; agree severity definitions up front so the final report isn't a negotiation.
Beginner 1 — Name the sections. Objective: from memory, list the seven sections an RoE must contain and one sentence on each. Concepts: RoE structure.
Beginner 2 — Fix the vague scope. Objective: given the scope line "test the app," rewrite it to be specific for a local app on 127.0.0.1:8080 with a test database, including an explicit out-of-scope line. Concepts: scope, default-deny.
Intermediate 1 — Catch the drift. Objective: given a short "session log" where the tester follows a redirect from an in-scope app to an unlisted host, identify the exact step where scope was exceeded and state what the tester should have done. Concepts: scope drift, stop procedure.
Intermediate 2 — Write a stop procedure. Objective: for a local Docker lab, write a 3-line emergency-stop procedure (signal, action, who confirms) and explain when you'd invoke it. Concepts: emergency stop.
Challenge — Full RoE for a toy lab. Objective: write a complete one-page RoE for a fictional "toy shop" web app + database running only on localhost. Requirements: all seven sections, specific enough that a stranger could tell exactly what's allowed; forbid destructive tests; include a one-command stop. Do not test anything real. Concepts: the whole lesson; prepares you to build the lab in the next lesson.
Next: Setting up a local-only lab — building the isolated environment your RoE points at, so every technique you practice stays on hardware you own.