August 23, 2026
I Built a Tool to Automate the One Test I Kept Doing by Hand
IDOR

By Kafeero Mirembe Mercy
2 min read
After writing about IDOR the bug where changing an ID in a URL exposes someone else's data I kept running into the same tedious workflow while practicing on PortSwigger's labs: change the ID, resend the request, check the response, repeat. Ten times. Then twenty. It's the kind of repetition that's perfect for a script, so I built one: idor-scout, a small CLI tool that automates exactly that check.
I want to walk through what I built and, more importantly, how I built it because the habits matter as much as the code.
Keeping it small on purpose
It would have been easy to over-engineer this. Add a GUI, support ten auth schemes, build a plugin system. I didn't, deliberately. The whole tool is two modules: scanner.py, which holds the actual request/diff logic, and cli.py, which just parses arguments and calls into it.
That separation is the first habit worth calling out. Logic and interface are different concerns, and keeping them apart means I can test the scanning logic without ever making a real HTTP request I just mock the session object. A beginner project doesn't need to be simple in scope to be simple in structure. Scope and structure are different axes, and getting the second one right early saves a lot of pain later.
Designing for where I actually work
The tool has a --delay flag and writes plain-text output that saves cleanly to a file. Neither is accidental. I'm testing on a connection that isn't always reliable, and I wanted a tool that degrades gracefully one that doesn't assume a fast, stable line the way most security tooling quietly does. That's not a workaround I'm apologizing for; it's a design constraint that shaped a better tool. Low-bandwidth-first design forces you to think about output size, retry behavior, and failure modes in a way that "just assume good WiFi" never does.
The part that actually taught me something
Writing the tests taught me more about the vulnerability than writing the scanner did. To test test_endpoint() properly, I had to enumerate: what does a real IDOR look like in a response (200, non-empty body)? What does a
properly defended endpoint look like (403, empty body)? What about a redirect to a login page — is that a false negative I need to handle?
Forcing myself to write those cases down as assertions turned "IDOR" from a concept I could describe into a set of concrete, testable conditions. That's the real value of writing tests for a security tool: they're not just proving the code works, they're proving you actually understand the failure mode you're automating against.
What's next
The roadmap in the README is honest about where this stands JSON output, rate limiting, broader auth support. I'm building it in public, alongside the CPTS material, because I think the most useful portfolio isn't a pile of finished projects. It's a visible trail of someone learning to build tools the way working pentesters actually do: small, tested, documented, and shaped by the real constraints they're working under mine being a laptop and a connection that don't always cooperate, in Uganda, not a lab in San Francisco.
The repo is up, MIT-licensed, with a working test suite and a CI workflow that runs on every push. If you're on a similar road toward CPTS or just starting with security tooling, feel free to fork it, break it, or tell me what you'd add.
I'm Mercy, a cybersecurity and digital forensics student in Uganda, and co-founder of CodeOn. This is part of a series documenting my path to CPTS.