Security bug reports for in-house QA (without writing an exploit)
You are testing the invoice page on staging. You change the number at the end of the URL by mistake, and a different company's invoice loads on your screen. You are not a security researcher, and you have no idea how serious this is. But you found something real, and now you have to tell someone.
This guide is for that moment. It is for in-house QA testers reporting a suspected security problem to their own engineering team.
Short version
- Stop the moment you see something wrong. Do not keep digging.
- Report what you saw, not how someone could attack it.
- File it in a private place, never in the public backlog.
- Use test accounts only, on staging, never on production.
- Blur or remove tokens and personal data before you attach anything.
- Let the security owner decide how bad it is. That is their job.
You do not need an exploit to file a security bug
Your engineers do not need proof that the door can be kicked in. They need to know the door was unlocked.
An exploit is code or a crafted input built to abuse a flaw on purpose. You do not need one, and you should not write one. Plain observations are enough.
Here is what QA testers find every week, without doing anything clever:
- A password appears in plain text in a response body in your network tab.
- You log out, press the back button, and your session still works.
- You change an ID in the URL and another user's record loads.
- An admin-only page opens for a standard test account.
- An API key or token is printed in the browser console.
- An invite link from three months ago still works.
Each one is a normal thing to notice during normal work. Each one is worth a report.
What you saw, why it matters, who gets it
Different observations go to different people.
| What you saw | Why it matters | Who to route it to |
|---|---|---|
| Password visible in a response body | Anyone with log access could read real passwords | Security contact, high priority |
| Session still valid after logout | Shared or public computers stay logged in | Backend or platform team |
| Another user's data after changing a URL ID | One account could read many accounts' data | Security contact, high priority |
| Admin page loads for a normal account | A regular user may reach controls they should not | Backend or platform team |
| Token or key printed in the console | Anyone watching the screen can copy it | Frontend team plus security contact |
| Expired invite link still works | Removed people may regain access | Product owner plus backend team |
If you are unsure which row you are in, route it to the security contact. Being over-cautious costs one message.
Stop at the first sign of a problem
When something looks wrong, stop. Take a screenshot, note the time, and write your report. Do not keep going to see how far it goes.
You changed one ID and saw one record, so why not try ten more? Do not. Here is why:
- You may cause damage. A page showing another user's record may also have a delete button that works.
- You pollute the evidence. Fifty odd requests from your account hide the real timeline in the logs.
- You may break a rule. Rules on accessing data you are not allowed to see rarely have a "but I was testing" exception.
- Measuring scope is not your job. Your job is to find and report.
One observation, clearly written, beats an hour of poking around.
Rules of engagement
- Test accounts only. Use accounts like [email protected]. Never sign in as a real customer.
- Staging only. Work on https://staging.example.com. Do not repeat a suspected security problem on the live site to "confirm" it.
- Never delete or change other users' data. If you can see another account's record, look and leave.
- Never pull real customer data. If a page shows real names, emails, or card details, close it. Do not export or copy it.
- Do not share widely. No screenshots in the company-wide channel. No "hey look at this" in a group chat.
- Redact before attaching. Blur tokens, session cookies, API keys, real names, and email addresses in every screenshot.
- Do not tell people outside the company. Not on social media, not in a forum, not to a friend who works in security.
What to do instead
Some habits feel helpful but make things worse.
- Instead of trying ten more IDs, report the one you saw and say you stopped.
- Instead of the public backlog, file it in the private security channel.
- Instead of retesting on production, note that you only tested staging.
- Instead of attaching a raw screenshot with a token in it, blur the token first.
- Instead of "I could probably take over any account", write "I saw another user's invoice at this URL".
- Instead of waiting until you understand the cause, report the observation today with the cause unknown.
That last point matters. You are allowed to file a report that says "I do not know why this happens." Diagnosis is engineering's job.
Where to file it
A security bug does not go where a broken button goes.
Good places: a private security channel, a restricted ticket only the security group can see, or a direct message to your named security contact. A security@ address works too.
Bad places: the public backlog, the shared QA board, the general engineering channel, a customer-visible roadmap tool, or a comment on an existing public ticket.
A public ticket describing an unlocked door is an instruction manual for everyone who reads it, including contractors and anyone who joins the tool later. Keep the details in a small circle until the fix ships.
If you do not know your security contact, ask your team lead in a direct message: "I have a possible security finding, who should get it?" Do not describe the bug until you know where it is going.
How to frame impact in plain words
Engineers triage by impact. You do not need a severity score. You need three plain sentences.
- What could someone do with this? "A normal account could read invoices belonging to other companies."
- How many users could be affected? A guess is fine, if you say it is a guess.
- What kind of data is involved? Names and emails are one thing. Payment details, passwords, and health data are another.
Weak: Found a security issue on the invoice page, looks bad.
Strong: A normal test account loaded another company's invoice by changing the ID in the URL. The page showed a company name and a total. This may apply to any invoice, not just the one I opened.
The second version lets a lead set priority in ten seconds.
The internal security bug report template
Copy this, fill it in, and send it to your security contact.
Title: Possible security issue — another user's invoice loads after changing the URL ID
Severity guess: High (my guess only — please confirm)
What I observed
I opened https://staging.example.com/invoices/4412 and the page
loaded an invoice belonging to a different company.
Account used
[email protected] (QA test account, standard user role)
Environment
Staging: https://staging.example.com
Chrome 141 on macOS 15
Build: staging-2026.08.02-b17
When it happened
2026-08-03 at 10:42 UTC
What I did before I stopped
1. Signed in as [email protected]
2. Opened my own invoice at /invoices/4410
3. Changed the URL to /invoices/4412
4. The page loaded with a different company name and total
5. I stopped here.
Possible impact (plain terms)
A normal signed-in user may be able to read invoices belonging to
other customers. The page shows company name, invoice total, and
billing email. I do not know how many records are reachable.
Evidence
Screenshot attached. Company name, billing email, and the session
cookie in the network panel are blurred.
Console / network notes
No console errors. GET /api/v1/invoices/4412 returned 200 instead
of a permission error.
What I have NOT done
- Did not test on production
- Did not open other users' records beyond the one above
- Did not change or delete any data
- Did not share this outside this channel
The "what I have not done" section is short and it earns a lot of trust. It tells the security owner exactly where your footprints are.
Attaching evidence is the slowest part. Browser-based tools like Crosscheck capture the screenshot, console output, network requests, and environment details in one step when you report from the page, so you spend your time on the write-up instead of collecting files. Check the captured data for tokens and personal details before you send it.
After you send it
Send the report and leave it alone. Do not follow up in a public channel. Do not add more testing while you wait.
If someone asks you to reproduce it, get that request in writing and stay inside the same limits: test account, staging, no data changes. If they ask you to check production, ask who approved it.
If nobody responds in a day, send one reminder in the same private channel. After that, escalate to your manager privately, still with no details in public.
Frequently asked questions
What if I am wrong and it is not a security bug? That happens often, and it is fine. A false alarm costs five minutes. A missed real problem costs much more.
Should I try to prove the bug before reporting it? No. One clear observation is enough. Extra attempts add risk and make the logs harder to read.
Can I use the normal bug tracker if my team is small? Only if the ticket can be made private and limited to the people who need it. Otherwise, direct message your lead.
What if I already saw real customer data? Say so in the report, plainly. Do not save it, screenshot it unblurred, or share it. Your team may need to log it for compliance, and they can only do that if you tell them.
Do I need to suggest a fix? No. A cause or a fix is optional, and mark it clearly as a guess. Your value is the accurate observation.




