Ethics, law and scoping
A penetration test is the same actions a criminal takes, made legal by one thing: written permission for a defined target. This first lesson is the one that keeps you out of prison and out of trouble. You will learn how to get real authorisation, write a scope and rules of engagement that protect both sides, and set the hard limits you never cross, before you touch anything.
By the end you can
- Explain why written authorisation is the only thing that separates testing from a crime, and who can sign it
- Write a scope that lists in-scope targets, out-of-scope systems and third-party assets that need the provider's permission
- Draft rules of engagement with test windows, rate limits, stop conditions and an incident path
- Choose an engagement type and name the methodology you will follow
- Handle evidence and confidentiality correctly, and test only the course's practice environment
The everyday picture
A locksmith and a burglar do the same thing: they open a lock that is not theirs. The difference is not skill. It is that the locksmith was called by the owner, agreed what to open and what to leave alone, carries something that proves it, and stops the moment the owner says stop. Take away the owner's say-so and the locksmith is just a burglar with good tools.
A penetration tester lives on exactly this line. The techniques in the rest of this course, the scanning, the broken access control, the stolen session, the escalated account, are the techniques an attacker uses. What makes your work legal and useful is the paperwork you agree before you start: who gave permission, over which systems, during which hours, with which actions off limits, and what you do if something goes wrong. Get that right and everything else in the course is a craft. Get it wrong and the best finding in the world is evidence against you.
Authorisation is everything
Accessing a computer system you have not been permitted to access is a crime in most countries. In the United States it is the Computer Fraud and Abuse Act (CFAA). In the United Kingdom it is the Computer Misuse Act. Most other countries have their own version, and the details differ: what counts as access, whether intent matters, how damage is measured, and how heavy the penalty is. The exact law is not the point for this lesson. The point is that the default state of any system that is not yours is off limits, and that a good result does not make an unauthorised test legal.
So every engagement rests on one document: written authorisation. Testers often call it the authorisation letter or, informally, the "get out of jail free" letter, because if your activity is ever questioned, it is the proof that the owner asked for it. A real authorisation names the exact systems, the dates and times, the kinds of testing allowed, the people doing it, and a signature. Keep a copy with you during the test, including a printed or offline copy, because the moment you most need it may be the moment the network is down.
Who can sign it matters as much as the signature. It has to be someone with the authority to accept the risk of the testing for those systems: the system owner or an executive who owns the business risk, not a friendly middle manager who happens to run the team. A manager saying "sure, go ahead" in a chat message is not authorisation, and it will not protect you or them. If a third party runs part of the system, as Mangrove's Partner app is run by the outside agency Lagoon Digital, the client cannot sign away permission over the agency's servers. Someone with authority over those servers has to agree too.
Quick check
A store operations manager emails you "yes, go ahead and test the Partner app this week, I approve". Is that enough to start?
Written and specific is good, but the operations manager does not own the risk for servers an agency runs, and an email is not the signed authorisation that protects both sides. Regulators do not sign pentest authorisations; the system owner does.
Scope: what you may touch, and what you may not
The scope is the fence around the engagement. It has two halves, and both matter. The in-scope list names exactly what you may test: specific applications, host names, IP address ranges, maybe a set of user roles. The out-of-scope list names what you must not touch even though it sits right next to the targets: the production database, a payments provider, the staff email system, anything belonging to another customer on shared infrastructure. Writing "out of scope: everything not listed above" is good practice, but naming the tempting neighbours explicitly stops arguments later.
Three traps catch new testers. First, third-party and cloud assets. If the client's app runs on a cloud provider, or sends traffic through a content delivery network or a payment gateway, those companies own that infrastructure. The client cannot give you permission over it, and many providers require their own notice or approval before any testing. You test the client's application, not the provider's platform. Second, data handling. The scope says what you may do with anything sensitive you find: usually, you must not copy real customer or payment data off the systems, you prove access with a redacted screenshot rather than a download, and you delete any extract when the test ends. Third, test accounts only. You use accounts the client created for the test, not a real employee's or customer's login, so you never act as a real person or touch their data.
This course gives you one scope that never changes. Every technique in every later lesson, the reconnaissance in Reconnaissance, the web attacks in the lab Partner app, the network work, the privilege escalation up to the lab directory domain, runs against a purpose-built practice environment: a sandboxed copy of the Partner app, a small practice network of store servers, and a lab directory domain. These are built to be attacked and belong to the course. They are your entire in-scope list. Real Mangrove systems, real companies, your employer, your neighbour's router and any live service on the internet are out of scope, always, with no exceptions.
Quick check
While testing the in-scope practice Partner app, you notice it loads images from a real cloud storage provider, and you wonder whether that bucket is misconfigured. What is the right move?
Third-party infrastructure belongs to the provider, not the client, and the client cannot authorise testing of it. You record what you saw and let the client take it up with the provider through the proper channel. Probing or downloading would be unauthorised access to someone else's system.
Rules of engagement: how you will behave
If scope is where you may go, the rules of engagement (RoE) are how you behave once you are there. A good RoE is written to protect the client's live business and its real people, because even a test against a practice system can spill over if you are careless. The core clauses recur in almost every engagement:
- Allowed times and windows. When testing may run. Noisy or risky actions are often pushed to off-peak hours so that if something slows down, few people are affected.
- Rate limits and intensity. Caps on how hard you hit a system, so a scan does not become an accidental denial of service that takes a system down.
- No destructive tests. You demonstrate a weakness without deleting data, corrupting records or leaving the system broken. Proving you could delete a table is not the same as deleting it.
- No social engineering of real staff unless it is explicitly authorised and separately scoped. You do not phish, call or trick real employees on a whim.
- No touching real customer data. Test accounts and test data only, so no real person is affected.
- Stop conditions. The situations where you pause immediately and call your contact: a system becomes unstable, you find signs of a real prior breach, or you reach anything that looks like real sensitive data.
The RoE also sets the communication path: named emergency contacts on both sides, reachable during the test window, and how fast you must report a serious problem. Two cases deserve a planned response. If you accidentally cause an outage, you stop, call the contact, and help restore service before you carry on. And if you find evidence that a real attacker got there before you, you stop testing that system at once and follow an agreed incident path to the client's security team, because you may be standing in the middle of a live crime scene. You are a tester, not the incident responder, and trampling the evidence helps no one. Real incident handling is its own discipline, covered in the defensive course lesson on the first hour of an incident.
Quick check
Your RoE says "no destructive testing". You find a flaw that lets you delete any order in the practice Partner app. What demonstrates the finding within the rules?
You prove the weakness and its impact in words and evidence, not by carrying out the destructive act. Deleting data, even once, even with a plan to restore it, breaks the rule and risks real harm. You never substitute your own guess for the agreed limit.
Engagement types, methodology and disclosure
Engagements differ in how much the tester is told up front, and the scope document should say which applies. In a black box test you start with almost nothing, like an outside attacker. In a white box test you are given source code, architecture and credentials, which finds more in the same time. A grey box test sits between, often with a normal user account. An assumed breach test skips the break-in and starts from a foothold the client grants, to answer "if one laptop is compromised, how bad does it get?" None is more correct; each answers a different question, and this course moves through several as it goes.
Professional work follows a named methodology rather than poking at random, so that coverage is consistent and the report is defensible. You should know these by name: the Penetration Testing Execution Standard (PTES), the OSSTMM, NIST SP 800-115, the OWASP Web Security Testing Guide (WSTG) for web applications, and the PCI DSS penetration testing guidance for cardholder environments. They overlap, and you cite the one you followed in the report so the reader knows what was and was not covered.
Finally, know the difference between three things people muddle. An engagement is a scoped, paid, time-boxed test under authorisation, which is this course. A bug bounty is a standing programme where a company invites anyone to report flaws under published rules, usually for a reward. Responsible disclosure is the ethic of telling the owner privately and giving them time to fix an issue before it is made public. All three share one root: you only test what you are permitted to test, and the permission's shape is different in each. Outside a scope, a bounty's rules or a clear invitation, there is no permission, and no permission means do not touch.
Build it
Write a scope and rules-of-engagement section you could put in front of a client, using a reusable template. Fill it for the course's practice environment.
Start from a template with both halves of the scope
Keep in-scope and out-of-scope side by side so a reader can see the fence at a glance. Name the tempting neighbours in the out-of-scope list, not just "everything else".
Markdown# Engagement: practice Partner app and store network Authorised by: (name, role that owns the risk) ______ Signature/date: ______ Also authorised by (third party): Lagoon Digital (runs the servers) ______ ## Scope In scope: - Practice Partner app and its API - Practice store network: 10.20.0.0/16 - Lab directory domain: lab.example Out of scope (do not touch): - Real production systems and real Mangrove data - Cloud provider platform, CDN, payments gateway (third parties) - Real customer, shop or staff accounts and their dataWrite the rules of engagement
Set the window, the intensity, the forbidden actions, and the stop conditions. Every clause should map to a real risk it prevents.
Markdown## Rules of engagement - Window: weekdays 20:00 to 01:00 local time - Intensity: rate-limited scanning; no action that could take a service down - Not allowed: destructive tests, social engineering of real staff, use of any real account, touching real data - Evidence: redacted screenshots only; no real data copied off systems; delete any extract at the end - Stop conditions: instability, signs of a real prior breach, or any real data reached. On a stop: pause, call the contact, do not continue.List emergency contacts and the incident path
Name a person on each side, reachable during the window, and say what happens if you cause an outage or find a real breach.
Markdown## Contacts and incidents - Client contact: Ken (engineering manager) — phone, backup phone - Security escalation: Mangrove security lead — phone - Tester lead: (you) — phone - If I cause an outage: stop, call Ken, help restore before continuing - If I find a real prior breach: stop on that system, notify the security lead immediately, preserve evidence, do not investigate furtherState the methodology and engagement type
One line that tells the reader how the test was run and what it therefore did and did not cover.
OutputType: grey box (a normal Partner app user account is provided) Methodology: PTES, with OWASP WSTG for the web application Deliverable: a report with findings, evidence, impact and fixes
Bring it to your team
Ask these before any test starts, whether you are the tester or the client reviewing a proposal.
- Who signed the authorisation, and do they actually own the risk for these systems?
- Does any target run on a third party's platform, and has that party agreed too?
- What is explicitly out of scope, and are the tempting neighbours named?
- What are the test window, the rate limits and the exact stop conditions?
- Who do we call if a system goes down or we find a real breach, and how fast?
- How is evidence handled, and are we certain no real customer data will be touched?
Red flags
- Authorisation that is only a chat message, or signed by someone who does not own the risk.
- A scope with no out-of-scope list, or that includes a third party's cloud without their permission.
- Rules of engagement that allow destructive tests or social engineering with no limits.
- No named emergency contact reachable during the test window.
- A plan to test against production with real customer data "to make it realistic".
Practice
Write a scope and rules of engagement
Mangrove asks you to test the practice Partner app and the practice store network (10.20.0.0/16), but not the lab directory domain this time. The practice store servers are busiest at midday. Write a short scope (in-scope and out-of-scope lists) and five rules of engagement for this engagement. Then name the one third-party dependency you would raise before signing.
- Your in-scope list names the practice Partner app and the store network range, and excludes the lab directory domain this time
- Your out-of-scope list names real production, real data and at least one third party such as the cloud provider or payments gateway
- Your rules include a test window away from the midday peak, a rate or intensity limit, no destructive tests, test accounts only, and a stop condition
- You identify a third-party dependency (for example the cloud storage the app uses) and say it needs the provider's permission before testing
Show a model answer
In scope: the practice Partner app and its API, and the practice store network 10.20.0.0/16. Out of scope: the lab directory domain this time, all real production and real Mangrove data, real shop and customer accounts, and any third-party platform including the cloud provider, the CDN and the payments gateway.
Rules of engagement: (1) test only in the evening window, since the store servers peak at midday; (2) rate-limit scans so they cannot take a service down; (3) no destructive tests, prove impact with redacted screenshots; (4) use only the test accounts provided, never a real login or real data; (5) stop and call the named contact on any instability, any real data, or any sign of a prior breach. The third-party dependency to raise before signing is the cloud storage the Partner app reads from: it belongs to the provider, so the client cannot authorise testing it, and the provider's own permission would be needed.
Spot the problems in a flawed authorisation email
A colleague forwards this as the whole approval for a test: "Hi, this is Sam from the ops team. You're good to test any of our systems whenever works for you this month, go as hard as you like to be thorough, and use the admin login admin / Summer2026 so you can see everything. Thanks!" List at least four problems with using this as authorisation, and say what a correct authorisation would include instead.
- You note the signer may not own the risk: "Sam from the ops team" is not shown to have authority to authorise testing of all systems
- You note the scope is unbounded ("any of our systems", "whenever") with no in-scope or out-of-scope list and no window
- You note "go as hard as you like" invites a denial of service, with no rate limit or no-destructive-tests rule
- You note using a real admin account is wrong: testing should use provided test accounts, and a password should never be shared this way
- You say a correct authorisation is a signed letter from the risk owner, with named in-scope and out-of-scope systems, a window, rules of engagement and emergency contacts
Show a model answer
The problems: the authority is unclear, because a member of the ops team is not shown to own the risk for "all our systems"; the scope is unbounded, with no in-scope or out-of-scope lists, no addresses and no dates; "go as hard as you like" has no rate limit and no ban on destructive tests, so a scan could cause an outage; and it hands over what looks like a real admin account, when testing should use purpose-made test accounts and credentials should never be emailed in plain text. There is also no confidentiality agreement, no emergency contact and no stop conditions.
A correct authorisation would be a signed letter from the person who owns the business risk (or an executive who does), naming the exact in-scope systems and the explicit out-of-scope ones, the test window, the rules of engagement including rate limits and forbidden actions, the test accounts to use, and named emergency contacts on both sides.
Code a scope gate: isInScope(target, scope)
Before any tool runs, a tester checks a target against the agreed scope. Write isInScope(target, scope) where scope is { allow: [...], deny: [...] } and each entry is either an exact host name or an IPv4 CIDR range like "10.20.0.0/16". Return { allowed, reason }. A deny match always wins, then an allow match lets it through, and anything not matched is denied by default. The reason is a short string.
function isInScope(target, scope) {
// Return { allowed, reason }.
// A scope entry is an exact host name or an IPv4 CIDR like "10.20.0.0/16".
// Rules: a deny match wins; then an allow match is allowed;
// anything not matched is denied by default.
}
test('an exact in-scope host is allowed', () => {
const scope = { allow: ['partner.lab.example', '10.20.0.0/16'], deny: ['admin.lab.example'] };
expect(isInScope('partner.lab.example', scope).allowed).toBe(true);
});
test('a deny match wins even when the host is also allowed', () => {
const scope = { allow: ['10.20.0.0/16'], deny: ['10.20.0.9'] };
expect(isInScope('10.20.0.9', scope).allowed).toBe(false);
});
test('an address inside an allowed CIDR range is allowed', () => {
const scope = { allow: ['10.20.0.0/16'], deny: [] };
expect(isInScope('10.20.5.37', scope).allowed).toBe(true);
});
test('an address outside every allow rule is denied by default', () => {
const scope = { allow: ['10.20.0.0/16'], deny: [] };
expect(isInScope('10.99.0.1', scope).allowed).toBe(false);
});
test('the result always carries a reason string', () => {
const scope = { allow: ['partner.lab.example'], deny: [] };
expect(typeof isInScope('something.else.example', scope).reason).toBe('string');
});
Show a solution
function ipToInt(ip) {
const p = ip.split('.');
if (p.length !== 4) return null;
let n = 0;
for (const part of p) {
const b = Number(part);
if (!Number.isInteger(b) || b < 0 || b > 255) return null;
n = n * 256 + b;
}
return n;
}
function matches(target, entry) {
if (entry.includes('/')) {
const [range, bitsStr] = entry.split('/');
const bits = Number(bitsStr);
const ip = ipToInt(target), base = ipToInt(range);
if (ip === null || base === null) return false;
const mask = bits === 0 ? 0 : (0xFFFFFFFF << (32 - bits)) >>> 0;
return (ip & mask) === (base & mask);
}
return target === entry;
}
function isInScope(target, scope) {
for (const e of scope.deny || []) {
if (matches(target, e)) return { allowed: false, reason: 'matches deny rule ' + e };
}
for (const e of scope.allow || []) {
if (matches(target, e)) return { allowed: true, reason: 'matches allow rule ' + e };
}
return { allowed: false, reason: 'not in scope: denied by default' };
}Deny is checked first so it always wins, then allow, then the fall-through returns a denial. The CIDR check compares the target and the range after masking off the host bits, so any address inside the range matches. A host name that is not a valid IPv4 address simply fails the CIDR check and falls through to deny by default.
Check yourself
A client's chief technology officer signs a detailed authorisation for a test of the practice Partner app, which runs on servers managed by the agency Lagoon Digital. What is still missing before you can test those servers?
Permission can only come from whoever owns the risk for a given system. The client owns the application but not the agency's servers, so the agency has to authorise testing of its infrastructure. No government permit is required, and budget is not what makes the test legal.
Mid-test you discover log entries that strongly suggest a real attacker compromised a practice-adjacent system weeks ago. Your rules of engagement list this as a stop condition. What should you do?
A real prior breach is a live incident, not part of your test. You stop, escalate at once through the agreed path, and preserve evidence. Continuing, deleting logs or running your own investigation can destroy evidence and interfere with the client's incident response, which is a separate discipline.
Which statement best captures the difference between a bug bounty and a penetration test engagement?
Both rest on permission; what differs is its shape. A bounty publishes rules anyone can act under at any time, and an engagement is a defined piece of work for one client under one authorisation. Neither is inherently illegal, and a bounty's rules are its form of permission, so it is not "no permission".
Flashcards
Key takeaways
- Written authorisation from the risk owner is the only thing that makes testing legal; a good result never excuses an unauthorised test.
- Scope has two halves: what you may test and what you must not, including third-party and cloud assets the client cannot authorise.
- Rules of engagement set windows, rate limits, forbidden actions, evidence handling and stop conditions to protect the live business.
- Name your engagement type and methodology, and keep emergency contacts and an incident path for outages or a real prior breach.
- In this course, the practice environment is the only thing you may ever test; real systems are always out of scope.
Sources and further reading
- NIST SP 800-115, Technical Guide to Information Security Testing and Assessment, NIST, 2008
- OWASP Web Security Testing Guide (WSTG), OWASP
- MITRE ATT&CK, a public knowledge base of real attacker tactics and techniques, MITRE
- Coordinated Vulnerability Disclosure Process, CISA
- PCI Security Standards Council (penetration testing guidance for cardholder environments)