A first-person guide to finding hidden inputs, chasing cache poisoning bugs, and levelling up your recon game — written for hunters at every level.
Reading time: ~12 minutes Skill level: Beginner to Intermediate Tools covered: Burp Suite (Community & Pro), Param Miner extension
Introduction: The Bug That Almost Got Away
I was three hours into a routine recon session on a public bug bounty target. I had crawled the app, mapped the endpoints, and poked every visible parameter I could find. Nothing. The surface looked clean, and I was close to moving on.
Then I remembered a tip I had seen in a PortSwigger tutorial: the most interesting parameters are the ones nobody told you about. I right-clicked a plain-looking request in Burp's site map, fired up Param Miner, and walked away to make coffee.
When I came back, the output tab was showing a parameter the app never advertised — one that reflected its value directly into the response body without any sanitisation. That single hidden input became the lead that eventually turned into a confirmed XSS report.
That day taught me something I now treat as a rule: parameter discovery is not optional — it is where the real attack surface lives. This post is everything I know about doing it efficiently with Param Miner.
What Are "Hidden" Parameters, Anyway?
Before we touch the tool, let us talk about the problem it solves.
Web applications accept input through many channels: URL query strings, POST body fields, HTTP headers, and cookies. The parameters a developer documents or displays in a form are only a fraction of the ones the back-end actually reads. There are often legacy inputs left over from old features, debug flags meant for internal use, A/B testing toggles, and undocumented API keys — all quietly accepted by the server but invisible to a casual observer.
PortSwigger defines these as hidden inputs — HTTP headers, cookies, or parameters that affect how a site responds to requests but are not used during normal interaction with the site. Because they are unintentionally exposed and often poorly validated, they are a goldmine for bug hunters. Common vulnerability classes that start with a hidden parameter include:
- Reflected XSS — the parameter value lands in the page without encoding
- Web cache poisoning — the parameter is reflected but not included in the cache key
- SSRF — a forgotten URL parameter is sent directly to a backend HTTP client
- IDOR — a numeric ID field grants access to another user's resource
- SQLi — an undocumented filter or sort field is passed raw to a query
The challenge is finding them. Manually guessing thousands of header names and query-string keys is not realistic. That is exactly what Param Miner automates.
What Is Param Miner?
Param Miner is a free Burp Suite extension developed and maintained by PortSwigger. It identifies hidden, unlinked parameters by comparing pairs of requests — one with a candidate input added, one without — and flagging any pair where the responses differ. It is particularly well-known for its power in finding web cache poisoning vulnerabilities, but its application goes far beyond that.
Key things it can guess for you:
TypeWhat it looks forGET parametersQuery-string keys appended to the URLPOST / body parametersFields submitted in request bodiesCookie parametersHidden cookie names the server readsHTTP headersCustom or legacy headers (e.g., X-Forwarded-For, X-Original-URL)
Param Miner ships with a built-in wordlist and also builds a session-specific wordlist by learning observed words from the responses it receives — so the longer it runs, the smarter its guesses become.
Installation
Method 1 — BApp Store (Recommended, Takes 60 Seconds)
This is the easiest path and works in both Burp Suite Community and Burp Suite Professional.
- Open Burp Suite.
- Click the Extensions tab (older versions show this as Extender).
- Select the BApp Store sub-tab.
- Type
Param Minerin the search bar. - Click Install.
- Burp will add a new Param Miner tab to the interface once installation is complete.
That is it. No restart required in most versions.
Note: Param Miner requires Burp Suite version 2021.9 or later. If you are running an older build, update Burp first.
Method 2 — GitHub / Manual Installation
If you are working in an air-gapped lab, prefer to pin to a specific version, or want to contribute to development, you can build Param Miner from source.
Prerequisites: Java JDK, Git
# 1. Clone the repository
git clone https://github.com/PortSwigger/param-miner.git
cd param-miner
# 2. Build the fat JAR (Linux/macOS)
./gradlew build fatjar
# Windows
# gradlew.bat build fatjar
# 3. Find the output JAR
ls build/libs/param-miner-all.jarOnce the JAR is built:
- In Burp, go to Extensions → Installed → Add.
- Set Extension type to
Java. - Browse to
build/libs/param-miner-all.jarand click Next. - Burp will load the extension and confirm success in the output pane.
The GitHub page also has release notes and changelogs — worth bookmarking if you want to track when new attack types are added.
Understanding the Param Miner Interface
Once installed, Param Miner adds its own tab to Burp. Inside you will find two important sub-sections:
- Settings — global configuration (concurrency, wordlists, attack options)
- Output / Results — a running log of every finding across all scans, accessible even after Burp Pro scan reports are closed
The settings panel exposes options I will cover in the tips section, but for everyday hunting you rarely need to touch them.
Step-by-Step: Running Your First Scan
Step 1 — Capture a Request
Browse to your target with Burp's proxy active. Let the Site Map populate under Target → Site map. Aim for requests that hit server-side logic — login pages, search endpoints, API calls, and profile-update routes are all good candidates.
Step 2 — Select Your Target Request
In the Site Map, click the request you want to analyse. You can select multiple requests by holding Ctrl (Windows/Linux) or Cmd (macOS) and clicking additional rows — Param Miner will queue them all.
Step 3 — Launch Param Miner
Right-click the selected request(s) and navigate through the context menu:
Extensions → Param Miner → Guess paramsA small configuration dialog will appear asking which type of hidden inputs you want to probe.
Step 4 — Choose Your Attack Mode
OptionWhen to use itGuess GET parametersEndpoint accepts query strings; you want to find hidden keysGuess cookie parametersSession-handling endpoints; look for debug or privilege cookiesGuess headersAny endpoint — great for cache poisoning leadsGuess everything!Comprehensive sweep; slower but misses nothing
For an initial recon pass, I usually start with Guess headers because header-based findings tend to have higher severity (cache poisoning, SSRF). Then I follow up with Guess GET parameters on the most interesting endpoints.
Step 5 — Review the Output
Results appear in two places:
- Param Miner tab → Output — always available, logs every discovered parameter with the endpoint and evidence.
- Burp Suite scanner issues — if you are on Burp Pro, confirmed findings are also raised as scanner issues in the Dashboard and Target tabs.
For each finding, Param Miner shows you the parameter name and the pair of responses that differ. Your job is to take that parameter name into Repeater and explore what it does.
Step 6 — Verify Manually in Repeater
This step is non-negotiable. A parameter flagged by Param Miner tells you the server responds differently when that input is present — it does not tell you why or how. Open Repeater, add the discovered parameter, and start probing:
- What happens if you change the value to
1,true,admin, or../? - Does the value appear anywhere in the response body or headers?
- Does the server return a different HTTP status code?
- Does the response size, timing, or content change in a meaningful way?
The answer to those questions determines whether you have a lead worth developing into a report.
Real-World Bug Bounty Examples
Hidden XSS via a Parameter Named q
A researcher testing a search endpoint used Param Miner to probe for hidden GET parameters. The tool surfaced a parameter called q that the application never displayed in the visible UI. When the researcher appended ?q=<script>alert(1)</script> to the request, the payload was reflected directly into the page without HTML-encoding.
The root cause was a combination of two failures: the application relied on client-side validation (which only checked visible form fields) and the server-side code simply echoed the q value into a JavaScript context. Because the parameter was undocumented, it had never been reviewed during a code audit. The finding was confirmed as a stored XSS with a direct impact on users of the affected search feature.
Lesson: Hidden parameters often bypass the input validation applied to their "official" siblings, precisely because no one knew to include them.
Example 2 — Cache Poisoning + XSS via an Unkeyed Header
In a public write-up on Infosec Writeups, researcher Vuk Ivanovic described using Param Miner against a live bug bounty target. Param Miner discovered a hidden HTTP header parameter whose value was reflected inside the body of the site's main page. Because the header was not included in the CDN's cache key, the poisoned response was served to every subsequent visitor who hit the same cached URL — turning a reflected input into a stored, worm able XSS.
Ivanovic notes: "Aside from testing for hidden parameters, [Param Miner] also tests for cache poisoning, and then there's Burp Pro with its scanner which tests for XSS. Add them together and you can get yourself some nice bounties."
This combination — Param Miner surfacing the unkeyed header, Burp Scanner confirming the XSS — is a workflow I now follow on every target that sits behind a CDN.
Example 3 — Fat GET Cache Poisoning (James Kettle / Black Hat 2020)
James Kettle, PortSwigger's Director of Research, demonstrated fat GET cache poisoning at Black Hat USA 2020 and released a dedicated Param Miner scan mode for it. The attack works when an application accepts GET requests with a body — the body content is processed by the server but excluded from the cache key. An attacker who supplies a malicious payload in the GET body can poison the cache for every legitimate user who requests that URL.
To reproduce the workflow in Burp:
- In the Site Map, select everything in scope.
- Right-click → Extensions → Param Miner → Bulk Scan → Fat GET.
- Param Miner sends paired requests (with and without a body) and flags responses that differ.
- Confirm in Repeater by injecting
alert(1)as the body value, then clearing the cache entry and re-requesting the URL with a normal GET.
Kettle's full research, Web Cache Entanglement, is required reading if you are serious about cache poisoning bugs.
Cache Poisoning Detection: A Closer Look
Cache poisoning deserves its own section because Param Miner has specific features designed for it.
How It Works
Web caches store responses and serve them to subsequent visitors. The cache decides what to store based on a cache key — usually the URL and a few headers. Any input that affects the response but is not part of the cache key is called an unkeyed input. If an attacker can control an unkeyed input and its value lands in the response, they can poison the cache.
Param Miner's Cache Poisoning Workflow
Param Miner adds a cache buster parameter (fcbz=1) to every request it sends by default. This prevents your probing from accidentally poisoning the real cache for other users — an important responsible-disclosure consideration.
The try cache poison setting (in the Attack Config panel) tells Param Miner to go a step further: when it detects a reflective unkeyed header, it automatically tests whether that header's value can be used to poison a cached response. You get a direct signal rather than having to manually confirm every header finding.
What to Check After a Finding
Once Param Miner flags a potential cache poisoning issue, validate it with these steps:
- Append a unique cache-buster query parameter (e.g.,
?cb=youruniqueid) to isolate your test. - Send the request with the poisoned header value. Look for the value in the response.
- Send a clean request without the header to the same URL + cache-buster.
- Check response headers for caching signals:
X-Cache: HIT,CF-Cache-Status: HIT,Age: <non-zero>. - If the poisoned value appears in the "clean" response, the cache is storing it. You have confirmed the bug.
Configuration Tips
Use a Custom Wordlist
The built-in wordlist covers common parameters, but targets in niche sectors (finance, healthcare, e-commerce platforms) often use domain-specific parameter names. I maintain a personal wordlist built from:
- Past bug bounty reports in the same domain
- JavaScript files from the target (extracted with tools like
linkfinder) - Open-source API documentation for frameworks the target likely uses
In Param Miner's Settings tab, toggle Use custom wordlist and point it to your file.
Enable Auto-Mine
The auto-mine headers and auto-mine params settings instruct Param Miner to passively launch guessing attacks based on traffic flowing through your proxy — without needing a manual right-click. This is useful for long hunting sessions where you want coverage without micromanaging every request.
Learn Observed Words
With learn observed words enabled, Param Miner extracts words from every response it receives and adds them to the current session's wordlist. Over a long session, this dramatically improves coverage because the tool learns the application's own vocabulary and uses it as guesses.
Skip Uncacheable Responses
If your focus is cache poisoning and you want speed, enable skip uncacheable — this tells Param Miner to skip endpoints where the response includes no-cache directives, since those pages will never serve cached content to other users anyway.
Respect Rate Limits
Param Miner sends a high volume of requests. On bug bounty programs with strict rate limits or WAFs, this can get you blocked or, worse, flagged as abusive behavior. I always check the program's rules before running any automated scan. For sensitive targets, I reduce concurrency in the Settings tab and run scans during off-peak hours.
Common Pitfalls
Pitfall 1 — Treating Every Finding as a Vulnerability
Param Miner flags parameters where responses differ, not parameters that are exploitable. A different Content-Length, a changed timestamp in the body, or a rotating session token can all produce false-positive signals. Every finding needs manual verification in Repeater before you write a report.
Pitfall 2 — Skipping the Cache Buster
Running Param Miner against a live cache without the fcbz cache buster enabled risks poisoning the real cache for genuine users. This can violate the bug bounty program's rules of engagement and cause real harm. Always verify that the cache buster option is active before scanning anything in production.
Pitfall 3 — Running Against Out-of-Scope Hosts
Param Miner, especially with auto-mine enabled, will follow your browsing wherever you go. If you accidentally browse to an out-of-scope domain while auto-mine is active, the extension will start scanning that host. Scope your Burp target carefully under Target → Scope and enable Use advanced scope control to be precise.
Pitfall 4 — Ignoring Community Edition Limitations
Param Miner works in both Burp Community and Burp Pro, but with differences. In Community Edition, scan results are not surfaced as scanner issues in the Dashboard — you must check the Param Miner Output tab manually. Some advanced integration features (like automatic passive scanning of flagged parameters) also require Pro. Knowing these limits prevents you from thinking a scan "found nothing" when the results are simply stored elsewhere.
Pitfall 5 — Not Reading the Output Carefully
The Param Miner output can get long, fast. I have seen hunters glance at it, see "no critical issues," and move on — missing a gold-standard finding buried two screens down. Build a habit of reading the full output and noting every parameter name, even the ones that look boring.
My Personal Workflow
Here is the routine I follow on every new bug bounty target:
- Browse manually for 20–30 minutes with Burp proxy active to populate the Site Map.
- Sort the Site Map by response size — unusual sizes often indicate interesting server-side logic.
- Select the top 10–15 most interesting requests (login, search, profile update, API endpoints).
- Right-click → Guess headers first. Header findings have the highest average severity in my experience.
- Let it run while I review JavaScript files for additional parameter names to add to my custom wordlist.
- Follow up with Guess GET parameters on endpoints that return dynamic content.
- Verify every finding in Repeater before writing a single line of the report.
- Document as I go — parameter name, endpoint, observed behaviour, and any payloads I tried.
Step 8 sounds obvious, but I have lost track of promising leads because I forgot to note them before moving on. A simple Markdown notes file open next to Burp is all I need.
Quick Reference: Param Miner Cheat Sheet
INSTALLATION
BApp Store: Extensions → BApp Store → Search "Param Miner" → Install
GitHub: git clone https://github.com/PortSwigger/param-miner
./gradlew build fatjar → load build/libs/param-miner-all.jar
LAUNCHING A SCAN
Target → Site map → Right-click request(s)
→ Extensions → Param Miner → Guess params
SCAN MODES
Guess GET parameters Query-string key bruteforce
Guess cookie parameters Cookie name bruteforce
Guess headers HTTP header name bruteforce
Guess everything! All of the above
CACHE POISONING
Bulk scan → Fat GET Tests for fat GET cache poisoning
Attack Config → Automatically tests reflective
try cache poison unkeyed headers for poisonability
Attack Config → Appends fcbz=1 to avoid real
Add 'fcbz' cachebuster cache pollution (ON by default)
RESULTS LOCATION
Burp Community: Param Miner tab → Output
Burp Pro: Dashboard → Issues AND Param Miner Output
KEY SETTINGS
learn observed words Grows wordlist from response content
auto-mine headers Passive scans proxy traffic (headers)
auto-mine params Passive scans proxy traffic (params)
use custom wordlist Load your own wordlist file
skip uncacheable Skip no-cache responses (cache focus)
max one per host Prevents multi-scan rate-limit issues
scan identified params Run Burp Scanner on found params (Pro)Closing Thoughts
I started bug bounty hunting thinking recon meant finding subdomains. It took tools like Param Miner to show me that the most interesting attack surface is often invisible — quietly sitting in the server-side logic, waiting for someone to ask the right question.
Param Miner asks thousands of those questions for you, systematically, in minutes. It does not hand you a vulnerability — it hands you a lead. The craft is in what you do with that lead: understanding why the server responded differently, tracing the code path in your head, and imagining what could go wrong if the wrong value ends up in the wrong place.
If you are new to bug bounty hunting, make Param Miner part of every engagement from day one. If you are more experienced and have been skipping parameter discovery because the visible surface looks clean — stop skipping it. The best bugs are not on the surface.
They are the ones nobody thought to document.
Further Reading
- Param Miner GitHub Repository — source code, changelogs, build instructions
- Unofficial Param Miner Documentation — detailed breakdown of every Attack Config setting
- PortSwigger: Checking for Hidden Inputs — official usage guide
- PortSwigger: Web Cache Poisoning Research — James Kettle's Black Hat 2020 research (fat GET, cache entanglement)
- Intigriti: Finding Hidden Input Parameters — five complementary techniques
- Cache Poisoning via XSS — Infosec Writeups — real-world write-up combining Param Miner + Burp Scanner
Written as part of my ongoing bug bounty journey. Questions, corrections, or your own Param Miner stories — drop them in the comments below.
Happy hunting. 🐛