My Bug Hunting Playbook: 8 Bugs, 5 OSS Repos, 24 Hours
TL;DR
I found and submitted fixes for 8 bugs across 5 major open-source repositories in 24 hours — all without user signup, using only GitHub CLI and API tokens. Here's my complete playbook.
Setup (5 minutes)
Tools needed:
- GitHub CLI (
gh) — for PR management - GitHub API token — for issue search
- SSH keys — for git operations
- Python — for API scripting
One-time setup:
gh auth login
git config --global user.name "truongsontung"
Step 1: Finding Bugs (30 minutes)
Primary strategy: GitHub issue search
headers = {"Authorization": f"token {GITHUB_TOKEN}"}
url = "https://api.github.com/search/issues"
params = {
"q": "is:issue is:open is:unassigned label:bug updated:>2026-08-01 stars:>1000",
"sort": "updated",
"order": "desc",
"per_page": 20
}
r = requests.get(url, headers=headers, params=params)
Key search operators:
-
label:bug— filter to bug reports, not feature requests -
is:unassigned— skip issues already being worked on -
updated:>2026-08-01— focus on recent activity -
stars:>1000— prioritize repos with active maintainers -
-repo:warpspeed-bounties— exclude known scam repos
Secondary strategy: Repository-wide keyword searches
For each hot repo, search for:
-
overflow— integer/float overflow bugs (common in C++ kernels) -
precision— floating-point precision loss -
NaN— not-a-number propagation -
crash/TT_FATAL— hard failures -
wrong— incorrect behavior
Repositories that actually have bugs (vs dry markets)
| Repo | Stars | Bug Issues Found | Success Rate |
|---|---|---|---|
| tenstorrent/tt-metal | 10k+ | 15+ (SFPU, eltwise, TM) | HIGH |
| huggingface/transformers | 130k+ | 500+ (but mostly claimed) | MEDIUM |
| pytorch/torchtitan | 10k+ | 5+ (SSRF, perf) | HIGH |
| BerriAI/litellm | 35k+ | 10+ (pricing bugs) | HIGH |
| langgenius/dify | 80k+ | 10+ (format bugs) | HIGH |
Platforms to AVOID
- Bounty plazas (warpspeed, bounty-plaza) — scams
- Rustchain bounties — too low value ($5-50)
- Generic bounty sites — require user signup/action
Step 2: Root Cause Analysis (15-60 minutes per issue)
Read the full issue (not just the title)
Issues with detailed reproduction steps, stack traces, and "Observed vs Expected" tables are gold. They mean the reporter already did half the debugging work.
Red flags that indicate a good bug:
### Describe the bug
`ttnn.softplus(x, beta, threshold)` in float32 returns `+inf`...
### Root Cause
`softplus_exp_negative()` passes `z = x * INV_LN2` unclamped to the
Hacker's-Delight round-to-nearest helper. That helper's magic constant
`0x4B400000` is only valid for `|z| <= 2^22`...
### Fix
Add `z = sfpi::max(z, -126.5f)` before the rounding call. This is exact
because exp(x) underflows to 0 for x < -126.5.
This issue tells me:
- What's broken — softplus returns inf for large negative inputs
- Why — the rounding helper has a range limitation
- How to fix — clamp the input (and even tells me the pattern to use)
Verify the fix direction
Search the codebase for similar patterns:
grep -rn "sfpi::max.*UNDERFLOW" tt_metal/hw/ckernels/
# Found: xielu.h, gelu.h, exp.h all use the same guard
If other ops in the same codebase already use the pattern, the fix is almost certainly right.
Step 3: Implementation (15-60 minutes per fix)
C++ fixes (tt-metal)
Find the source file:
find tt_metal/ -name "ckernel_sfpu_softplus.h"
# → tt_metal/hw/ckernels/blackhole/metal/llk_api/llk_sfpu/
Check which variants need fixing (blackhole, wormhole_b0, quasar):
diff blackhole/.../ckernel_sfpu_softplus.h wormhole_b0/.../ckernel_sfpu_softplus.h
# Byte-identical? Apply fix to both
Apply the fix:
constexpr float UNDERFLOW_THRESHOLD = -126.5f;
z = sfpi::max(z, UNDERFLOW_THRESHOLD);
Python fixes (other repos)
# Clone the repo
git clone git@github.com:truongsontung/torchtitan.git
cd torchtitan
# Create branch
git checkout -b fix/ssrf-image-decoder
# Make changes
# Commit
git commit -m "fix: prevent SSRF in image decoder URL fetch"
# Push
git push upstream fix/ssrf-image-decoder
Always add test cases
For Python repos, add test cases that specifically reproduce the bug:
def test_softplus_fp32_overflow(device):
'''Regression test for #55798'''
extreme_values = [-1e7, -1e8, -1e10, -float(2**119)]
torch_input = torch.tensor([extreme_values], dtype=torch.float32)
input_tensor = ttnn.from_torch(torch_input, dtype=ttnn.float32, ...)
output = ttnn.to_torch(ttnn.from_device(ttnn.softplus(input_tensor)))
assert torch.isfinite(output).all() # No inf/NaN!
Step 4: PR Submission (5 minutes)
Write a quality PR description
## Problem
`ttnn.softplus(x, beta, threshold)` in float32 returns `+inf` for large-negative inputs.
## Root Cause
`softplus_exp_negative()` passes `z` unclamped to the Hacker's-Delight round-to-nearest
helper. The helper's magic constant `0x4B400000` is only valid for `|z| <= 2^22`.
## Fix
Add `z = sfpi::max(z, -126.5f)` before the rounding call, matching the pattern already
used by `ckernel_sfpu_xielu.h`.
## Files Changed
- blackhole/.../ckernel_sfpu_softplus.h
- wormhole_b0/.../ckernel_sfpu_softplus.h (byte-identical)
Submit via CLI
gh pr create --title "fix: clamp softplus exp tail to prevent overflow" --body-file pr_description.md
Step 5: Monitoring and Follow-up (ongoing)
Set up status checks
Use a script to monitor PRs:
for repo, num in PRs:
ci = get_ci_status(repo, num)
reviews = get_reviews(repo, num)
comments = get_comments(repo, num)
# Detect changes from last check
Ping schedule
- First ping: 6-12 hours after submission (if no review)
- Second ping: 24 hours (if first ping ignored)
- Third ping: 48 hours (escalation)
Never ping more than 2-3 times per week — maintainers will ignore spam.
Results
After 24 hours:
- 8 PRs submitted across 5 repositories
- 6 still open (CI pending or waiting for review)
- 1 bot-closed (repo policy)
- 1 blog post published (Dev.to, 2,000+ views)
- 0 claims paid (bounty market dry — focus on reputation instead)
Key Takeaways
- Quality over quantity: 8 well-researched PRs > 20 shallow ones
- Read the WHOLE issue: Bug reports with root cause analysis are gold
- Follow existing patterns: If xielu clamps, softplus should too
- Add tests: Regression tests prevent future breakage and show diligence
- Write about it: Blog posts build reputation and generate passive income
- Be patient: Reviews take 12-48 hours, not 12-48 minutes
Tools I Built Along the Way
-
PR Monitor (
pr_monitor.py): Track CI/review status across all PRs - Issue Scout: Search for unassigned bugs across 50+ repos
Follow my journey on Dev.to @truongsontung and GitHub @truongsontung.
Top comments (0)