WhiteMage is currently #1 on Immunefi for earnings in 2025. Somebody asked about how people pick bug bounty targets. This was his response to it.
First, pick any topic; not target, topic. This can be specific functionality, a type of protocol or anything that is specific. The more specific the better. Next, find all projects with a bounty or a large TVL, like 20 of them. To me, this is unique. I tend to pick a project that is isolated and spend several months on it.
Go over each one of the projects to understand what they are doing. Notably, since they are all similar, note down how they do it and what could go wrong. To begin, just get the gist of it and don't go too deep. After a while, the same thing will be done over and over again. If something is being done differently, it's a good place to look at bugs.
Take time to look at suspicious things in depth. Go deeper and deeper into the intricacies of the functionality. With this, you'll gain more and more knowledge about this niche thing. These small details may lead to a bug or a wrong/sus pattern. Understand under what circumstances that this can be triggered and cause havoc. They refer to this as a almost crit.
At this point, you may have a lead at an issue. Save this and keep going! They have a great quote about it: " A lead is not a checklist bug, nor a vulnerability on a writeup. It's the understanding of something that on very specific scenarios can trigger a serious vulnerability."
Check all of the other projects for the same types of issues. It won't be exactly the same but there's a chance that similar types of mistakes were made. Now, prove that the issue leads to impact on the code. Prove this on all possible projects, write a PoC and report it.
For a bug on
Scroll, the cross-chain messaging had a
to.call(data), where the
to had some magic values that shouldn't be controllable. They learned this pattern from reading bridges in the past and noticed that a particular check was missing in this code.
Another bug was in
Story around block sizes. When Story/Omni changed the default block size maximum, this was fine. However, because the mempool is separated from the block creation in their protocol, this felt weird to the WhiteMage. A mismatch between expectations and reality seemed like a good path for a bug. Having experience with memory exhaustion and triggering node crashes seemed to help them.
He has a few
do-nots:
- Pick an amount of contracts that is actually doable. Don't pick all contracts on Ethereum.
- Don't read all of the code. Only Just read the common denominator between all of the projects.
- Don't follow checklists or writeups blindly. If it's on a checklist, it's probably been found. Feel free to use the checklist for inspiration but not much more.
They have a great quote at the end: "It's always some new idea around the same old concepts, but you have to do it for yourself. Then you can come up with some creative name like "read-only reentrancy" Thanks for sharing!