Step 314. Starting Bug Bounty — Understanding the System and Picking Your First Target
Level 4 — Bug Bounty | Difficulty ★★☆☆☆ | Estimated time: 2 hours
Prerequisites: you have finished Step 171 (OSINT advanced) attack-surface concepts and the Level 2–3 web vulnerability basics. You can read basic Python syntax.
- What you need: Python 3, a notepad (for the operations brief). Signing up for a real platform is optional, and every platform screen in this chapter is an example.
- ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime.
- Caution: bug bounty is legal only inside the scope and rules the program states. Even a single out-of-scope request can be illegal. This boundary is the premise of this entire Level.
Every attack technique you’ve learned so far could only be used inside a lab. Starting today, that’s different — there are companies in the world that publicly declare, "Attack our service, and if you find something, we’ll pay you." This is bug bounty. But it is not freedom; it is a contract. Today you learn not attack technique, but how to read that contract.
1. Learning Objectives
By the end of this chapter, you will be able to:
- Explain the structure of the bug bounty system (platforms, programs, triage)
- Find and read the scope, prohibited actions, and reward table on a program policy page
- Judge what a wildcard scope like
*.example.comincludes and excludes - State the difference between valid, duplicate, informative, and N/A verdicts
- Apply the first-target selection criteria to write one "operations brief"
2. Background Knowledge — Today’s Tools and Concepts
Today’s Tools at a Glance
| Category | Details |
|---|---|
| Language/environment | Python 3 (scope-judgment principle practice) |
| Today’s tools | (concept intro) HackerOne · Bugcrowd · KISA vulnerability reward program (KVE), (hands-on) scope-judgment script |
| Concepts needed | Scope, wildcards, reward tiers, verdict types, competition density |
| Today’s deliverable | 1 target program + 1 operations brief |
2-1. What Is Bug Bounty — A Contract with an Attack Permit Attached
A bug bounty is a program in which a company pays rewards for vulnerability reports against its own services. The core is this — it is the only zone in this entire book where offensive action against a real service becomes legal.
However, conditions apply. It is permitted only inside the scope (target domains, IPs, apps) and rules each program states. The scope is the permit’s valid area. A request to an out-of-scope system is just plain illegal intrusion, even mid-participation in a bug bounty.
2-2. The Platform Structure — Who Sits in the Middle
There are three representative channels. HackerOne and Bugcrowd are international platforms where countless companies’ programs gather. In Korea there is the KISA Software New Vulnerability Reward Program (KVE).
On a platform, the person you deal with is the triager (the report reviewer). When a report comes in, the triager reproduces it and issues a verdict. That flow — submit, review, verdict, reward — is bug bounty’s basic loop.
2-3. Scope and Rules — The Body of the Contract
A program policy page states four things. ① In-scope: the list of assets you may test. ② Out-of-scope: assets you must not touch. ③ Prohibited actions: behavioral rules like no denial-of-service testing, no social engineering, automated-scan rate limits. ④ Reward table: the amounts per severity tier.
Wildcard interpretation is what beginners get wrong most. If *.example.com is in scope, are all subdomains fair game? Is the root domain (example.com) itself included? Mobile apps? Third-party services (payment processors, etc.)? The correct answer differs per program, so only the sentences written on the policy page are the answer.
2-4. Verdict Types — Most Reports Aren’t Rewards
Submit a report and the answer that comes back is mostly one of four.
| Verdict | Meaning | Reward |
|---|---|---|
| Valid / resolved | Recognized as a real vulnerability | Yes |
| Duplicate | Someone reported it first | No |
| Informative | True, but weak security impact | No |
| Not applicable (N/A) | Cannot be considered a vulnerability | No |
One sobering fact — most reports end as duplicate, informative, or N/A. Taking time to reach your first valid verdict is normal, which is why the first goal must be not "a big payout" but "the experience of 1 valid verdict."
2-5. First-Target Selection Criteria — Go Where Competition Is Low
Famous programs like Google and Apple are swept daily by the world’s best hunters. A beginner’s odds of a first valid report there are low. The conditions of a beginner-friendly program are these.
- Wide scope — open as a wildcard (
*.domain), so there are many assets to explore - Low competition — a new program, or few participants (few resolved reports)
- A clear reward table — per-tier amounts written down, so you can set expectations
- Fast response — the average triage response time is published and short
3. Follow Along
3-1. Dissecting a Program Policy Page — Screen Example
Learn the typical shape of a policy page through a screen example. Sign up for a platform and open a real page, and it has exactly this structure.
Screen example (the shape of a HackerOne program policy page — a fictional program):
Example Corp Security Program
┌──────────────────────────────────────────────┐
│ Scope (targets) │
│ In scope: *.example-corp.com │
│ Example iOS/Android apps │
│ Out of scope: status.example-corp.com │
│ all third-party services │
│ │
│ Rules (prohibited actions) │
│ - No DoS/DDoS testing │
│ - No social engineering / phishing │
│ - Automated scans limited to 5 req/sec │
│ - No access to others' accounts or data │
│ │
│ Rewards │
│ Critical $5,000 / High $1,500 │
│ Medium $500 / Low $100 │
└──────────────────────────────────────────────┘
How to read it: look at the four boxes in order — targets, exclusions, prohibited actions, rewards. This page is the contract, and "I didn’t know" doesn’t work. The example’s program, domains, and amounts are all fabricated data.
3-2. Scope-Reading Practice — Four Questions
Look at the screen example’s scope and answer these four yourself.
| Question | The answer in this example |
|---|---|
Is api.dev.example-corp.com in scope? |
Yes — caught by *.example-corp.com |
Is the root example-corp.com in scope? |
Unclear — if not stated in the policy, ask or treat as excluded |
status.example-corp.com? |
No — explicitly excluded |
| The payment processor’s pages? | No — third-party services excluded |
How to read it: the core instinct is "if it isn’t stated, it isn’t in scope." The moment you test an ambiguous asset you may step out of the legal zone, so when it’s ambiguous, don’t — or ask the program first.
3-3. The Wildcard-Judgment Principle — Measured
Let’s judge "is it caught by *.lab.local?" in code. Watch how a machine interprets the policy sentence, and scope-reading becomes instinct.
Input: scope_check.py:
import re
scope_in = ["*.lab.local"] # in scope
scope_out = ["status.lab.local", "thirdparty.example.com"] # explicit exclusions
def in_scope(host):
for pat in scope_out: # exclusions always first
if re.fullmatch(pat.replace("*.", r"(.+)."), host):
return False, f"matches exclusion ({pat})"
for pat in scope_in:
if re.fullmatch(pat.replace("*.", r"(.+)."), host): # strict: subdomain required
return True, f"matches scope pattern ({pat})"
return False, "no scope pattern match"
tests = ["www.lab.local", "lab.local", "dev.api.lab.local",
"status.lab.local", "lab.local.evil.com", "thirdparty.example.com"]
for h in tests:
ok, why = in_scope(h)
print(f"{h:28s} -> {'IN ' if ok else 'OUT'} ({why})")
Output (measured 2026-09-09):
www.lab.local -> IN (matches scope pattern (*.lab.local))
lab.local -> OUT (no scope pattern match)
dev.api.lab.local -> IN (matches scope pattern (*.lab.local))
status.lab.local -> OUT (matches exclusion (status.lab.local))
lab.local.evil.com -> OUT (no scope pattern match)
thirdparty.example.com -> OUT (matches exclusion (thirdparty.example.com))
How to read it: three things to see. ① Deep subdomains like dev.api.lab.local are also caught by the wildcard. ② lab.local.evil.com is a different domain despite the similar look — OUT. ③ And most important — the root domain lab.local came out OUT. That’s because this judge interpreted *. strictly as "a subdomain must be present."
Why do this: real programs are split on this interpretation too. Some programs include the root domain and some don’t. So when the policy doesn’t state it, not touching the root domain is the safe default. Judge it yourself in code, and this ambiguity gets into your hands.
3-4. Reading the Reward Tier Table — Screen Example
Reward tables usually have four severity tiers. This is a screen example.
Screen example (a fictional program's reward table):
Critical — remote code execution, unauthenticated full DB access $5,000
High — account takeover of others, stored XSS (targeting admin) $1,500
Medium — IDOR (reading others' data), privilege escalation $500
Low — reflected XSS, information disclosure (limited) $100
How to read it: read the tier criteria sentences, not the reward amounts. Only when there’s a criterion like "reading others’ data = Medium" do you later have grounds to argue which tier your finding belongs to. Remember that even the same IDOR lands in different tiers depending on what data is exposed.
3-5. Writing the Operations Brief
Once you’ve picked your first target (or use the fictional practice program), make a one-page operations brief. This document is the boundary line for everything you do from here on.
# Operations Brief — (program name) / Date: ____
### Scope (never step outside it)
- IN: *.example-corp.com, mobile apps
- OUT: status.example-corp.com, all third-party services
### Prohibited actions
- No DoS / automated scans max 5 req/sec / no access to others' data
### Reward criteria (my target tier: Medium)
- Medium $500 — reading others' data, e.g., IDOR
### Reason for selection
- New program (few resolved reports), wide assets via wildcard scope
### My test accounts
- Account A: ____ / Account B: ____ (testing happens only between these two accounts)
How to read it: the "my test accounts" box matters. Bug bounty verification happens, as a rule, only between accounts you created yourself. Anything outside this brief is not "study" — it’s intrusion.
4. Missions & Exercises
Mission — Complete One Operations Brief
- Read the policy pages of 3 programs on a real platform (HackerOne, etc.), or use the fictional program from 3-1 as your target
- Build a table comparing the candidates on 2-5’s four selection criteria (scope width, competition, reward table, response speed)
- Complete an operations brief in the 3-5 format — including scope, prohibited actions, reward criteria, and reason for selection
- Add 3 hosts to 3-3’s
scope_check.py, run the judgment, and attach the result to the brief - Write "I will never step outside this document’s scope" on the brief’s last line, with the date
Exercises
Exercise 1. Explain from the "contract" perspective why attacks in bug bounty are legal, and why an out-of-scope request is illegal even while participating in a bug bounty.
Exercise 2. Using 3-3’s measured result as grounds, explain why the handling of the root domain example.com differs per program when *.example.com is in scope.
Exercise 3. Explain why a duplicate verdict is "common," not "a lack of skill," citing the structure of bug bounty.
Exercise 4. Give two reasons why "a program with wide scope and low competition" favors beginners.
5. Model Answers & Completion Criteria
Mission Model Answer
Example of the candidate-comparison table (program names fabricated):
| Criterion | Program A (famous) | Program B (new) |
|---|---|---|
| Scope | Limited to 3 domains | *.domain wildcard |
| Resolved reports | 4,000+ (fierce competition) | 30 (low competition) |
| Reward table | Clear | Clear |
| First-target fit | Low | High — selected |
How to verify: ① are the 4 comparison criteria in the table? ② is the IN/OUT scope transcribed into the brief word for word? ③ is the scope_check.py run result attached? ④ is the "never step outside" declaration present? All ‘yes’ means complete.
Exercise Answers
Answer 1. A bug bounty is a contract in which a company publicly promises "for this range (scope), under these rules, we permit testing," and the participant has accepted those conditions. The permission exists only inside the boundary called scope, so a request to an out-of-scope system is legally identical to an ordinary unauthorized intrusion. It is not the status of "bug bounty participant" that is protected — only "actions inside the permitted range."
Answer 2. In 3-3’s measurement, lab.local was judged OUT — because *. was interpreted strictly as "subdomain required." But that interpretation may differ from the program author’s intent. Some programs meant to include the root in *.example.com, and some actually list example.com separately. Because the mechanical interpretation diverges, when the policy doesn’t state it, you must leave the root domain alone or ask.
Answer 3. In a popular program, hundreds of hunters are looking at the same features at the same time. There is one vulnerability and several reports, so only the earliest report becomes valid and all the rest become duplicates. It’s a matter of timing, regardless of skill. So a duplicate verdict is accurately read as "had the skill to find it, but was late," and choosing a low-competition program is the strategy that lowers the duplicate rate.
Answer 4. First, a wide scope means many assets (subdomains, features) to explore, so there’s a higher probability that corners nobody has looked at yet remain. Second, low competition means a lower probability that someone submits first between your discovery and your report, so you get fewer duplicate verdicts. If the first goal is "the experience of a valid verdict," these two conditions raise the success probability the most.
Completion Criteria Checklist
- [ ] I can explain that bug bounty is "a contract that is legal only inside scope"
- [ ] I can find and read the policy page’s 4 elements (targets · exclusions · prohibitions · rewards)
- [ ] I verified the root-domain ambiguity of wildcard scopes hands-on
- [ ] I can distinguish and state the 4 verdict types (valid · duplicate · informative · N/A)
- [ ] I applied the 4 first-target selection criteria to compare candidates
- [ ] I completed one operations brief
6. Common Pitfalls & Fixes
Wall 1. Coveting the famous programs first
Symptom: you start by looking at the Google, Apple, Facebook programs.
Cause: choosing by reward amount.
Fix: the first goal is not money but the experience of 1 valid verdict. Famous programs are swept daily by the world’s best, so few vulnerabilities remain and the duplicate rate is high. Start with a new, wide-scope program per 2-5’s criteria.
Wall 2. Skimming the scope and starting
Symptom: thinking "it’s a wildcard, everything’s fair game," you test and touch an excluded asset.
Cause: not reading the policy page closely.
Fix: make 3-5’s operations brief before testing. The rule is: don’t touch assets not in the brief. Squatting domains that merely look similar, like lab.local.evil.com, are never in scope (3-3 measurement).
Wall 3. The judge’s result differs from my expectation
Symptom: you’re flustered that lab.local came out OUT in scope_check.py.
lab.local -> OUT (no scope pattern match)
Cause: not a bug but an intended strict interpretation — *. was implemented as "a subdomain must be present" (measured 2026-09-09).
Fix: this ambiguity itself is today’s lesson. In real policies too, when not stated, holding off on the root domain and asking the program is the safe default.
Wall 4. Getting discouraged by a duplicate verdict
Symptom: your first report comes back duplicate and you lose motivation.
Cause: reading duplicate as a signal of "no skill."
Fix: duplicate means "found it, but late" — and it’s evidence of skill. Structurally, most reports in popular programs end as duplicates (Exercise 3). Moving to a lower-competition program is the correct answer that raises the odds.
7. Summary
Today’s Concepts
| Concept | One-line explanation |
|---|---|
| Bug bounty | A system that rewards vulnerability reports — a contract legal only inside scope |
| Scope | The testing-permit zone — the IN/OUT list and prohibited actions are the contract’s body |
| Triager | The reviewer who reproduces reports and issues verdicts |
| 4 verdict types | Valid (reward) · duplicate · informative · not applicable (no reward) |
Wildcard *.domain |
All subdomains — whether the root domain is included varies per program |
| Operations brief | The boundary document of my activity — a summary of scope, rules, test accounts |
| First-target criteria | Wide scope · low competition · clear reward table · fast response |
Today’s Commands & Code
| Tool | What it does |
|---|---|
re.fullmatch(pattern, host) |
Judge whether a host exactly matches a scope pattern |
pattern.replace("*.", r"(.+).") |
Convert a wildcard to a regex (subdomain-required interpretation) |
| Check the exclusion list first | OUT beats IN — an explicit exclusion always wins |
The Core Instinct
What you learned today is not technique but boundaries. Bug bounty is not "a world where you may attack" but "a game where you read the permit and move only inside it." The habit of reading the policy page closely, the default of not touching what’s ambiguous, the attitude of reading duplicates as statistics rather than failure — these three are the roots of all of Level 4. Once the operations brief is complete, from here on you actually draw the map and find vulnerabilities inside that boundary.
Once every box is checked, Step 314 is complete.