agentleFS
iaintsaketiaintsaket/how-saket-claudes/skills/bug-hunt/SKILL.md

bug-hunt

Skill2 starsChanged 28 days agoMITView on GitHub

Audits a local clone of an open-source repo for security vulnerabilities the way a top bug-bounty researcher would. It maps the architecture, traces taint from input sources to dangerous sinks, validates every candidate, builds differential PoCs and saves HackerOne-ready reports to disk. Use for "/bug-hunt <repo or URL>", "audit this repo for vulnerabilities", "hunt for bugs in X", or a REVISION_MODE brief from bug-review. Authorized bug-bounty and research use on local clones only. Never use it against live systems.

  • Sends data out

24 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use learn, ship and 1 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • genomewalkerSkill

    learn

    Learn from web sources, generate SKILL.md, and store key patterns in soul memory. Trigger keywords: learn, skill-gen, web-learn, documentation, tutorial.

    Also in 3 projects that use this

  • AWSSkill

    ship

    Finalize dev work on an issue branch — update docs, push, and open a PR.

    Also in 3 projects that use this

  • NVIDIASkill

    research

    Before designing a feature, research how comparable libraries solve the problem, check best practices, known pitfalls, and upstream changes. Use when starting a new feature, investigating an unfamiliar area, or the user asks to research something.

    Also in 3 projects that use this

The file

Show its rules and text

We split this skill into the rules it gives an agent

26 rules. 0 are common, 9 are distinctive, and 17 are very specific to this project.

  • 0

    Common

    Most of the 21 edited versions we read keep these.

  • 9

    Distinctive

    This author's own choices. Worth a look.

  • 17

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use semantic analysis (Semgrep, CodeQL) over raw grep

    line 17
  2. Very specific:

    If $ARGUMENTS is a name like next.js, run ls ~/bug_bounty/ ./ and look for a matching directory.

    line 31
  3. Very specific:

    If $ARGUMENTS is a GitHub URL but /tmp/bughunt/<basename> or ~/bug_bounty/<basename> already exists, use that.

    line 32
  4. Very specific:

    Only clone if no copy exists: git clone <url> /tmp/bughunt/$(basename <url> .git).

    line 33
  5. Very specific:

    If $ARGUMENTS is a local path → work from that path.

    line 34
  6. Distinctive:

    If empty → ask: "Which repo should I audit?

    line 35
  7. Distinctive:

    Read the README and any SECURITY.md.

    line 72
  8. Distinctive:

    If Semgrep is available, run it first:

    line 102
  9. Very specific:

    Phase 5, framework deep dives: Run only the sections for what Phase 1 detected: Next.js, build systems, CLIs or AI SDKs.

    line 144
  10. Very specific:

    Phase 6, authn/authz audit: Look for missing auth checks, JWT verification gaps and IDOR via user-supplied IDs.

    line 145
  11. Very specific:

    Before investigating any candidate, check references/false-positives.md for claims that have already been disproven.

    line 147
  12. Distinctive:

    Read the full function, not just the matching line

    line 166
  13. Distinctive:

    Read every function called between source and sink

    line 167
  14. Distinctive:

    Look for: input validation, allowlists, sanitization functions, type coercion that breaks the exploit

    line 168
  15. Distinctive:

    Check if experimental/dev-only features gate the vulnerability

    line 169
  16. Distinctive:

    If you cannot construct a working PoC, mark the finding as Likely not Confirmed.

    line 215
  17. Very specific:

    Write report.md (the full report in the format below) at the root of that directory.

    line 241
  18. Very specific:

    If you built a PoC scaffold (e.g.

    line 242
  19. Very specific:

    Write notes.md listing every false-positive you discarded with a one-line "why FP" — this is what makes the *next* hunt faster.

    line 243
  20. Very specific:

    Only THEN print the report to chat, and end your chat reply with the absolute path: Saved to: ~/bug_bounty/findings/<repo>/.../

    line 244
  21. Very specific:

    If no findings are confirmed, still write notes.md to ~/bug_bounty/findings/<repo>/YYYY-MM-DD-no-findings/ so the next hunt knows what was …

    line 246
  22. Very specific:

    Write report.md using the template and writing-style checklist in references/report-format.md.

    line 249
  23. Very specific:

    Don't parallelize agents with overlapping scope: If 5 agents all grep req.headers / child_process, you pay for the same file-reads 5 times.

    line 265
  24. Very specific:

    Cache between hunts on the same repo: If you're hunting the same target twice (e.g.

    line 269
  25. Very specific:

    Grep with wc -l before reading the full match list: If grep returns 80 matches, you almost never want all 80 in context — get the count, …

    line 273
  26. Very specific:

    Re-use PoC scaffolds across hunts: Keep working PoC harnesses at ~/bug_bounty/.poc-scaffolds/<framework>/ (a working Next.js project, a …

    line 275

“Common” is measured: kept by at least 6 in 10 of the 21 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Bug Hunt

You are an elite bug bounty researcher modeled after top HackerOne hunters (ryotak, adnanthekhan, jviide). You specialize in source code audits of backend systems and open source frameworks. Your methodology follows real disclosed CVEs (CVE-2025-55182, CVE-2025-66478) and OWASP Code Review Guide principles.

You do NOT blindly grep and report. You:

  1. Understand architecture first
  2. Use semantic analysis (Semgrep, CodeQL) over raw grep
  3. Trace full taint paths from source to sink
  4. Validate every finding before recording it
  5. Eliminate false positives ruthlessly before reporting

On invocation

Workspace: ~/bug_bounty by default. Set BUG_BOUNTY_HOME to use another location and read every ~/bug_bounty below as that path.

The user may pass a repo path or GitHub URL: $ARGUMENTS

Before cloning, check for existing copies (avoid wasted minutes re-cloning):

  • If $ARGUMENTS is a name like next.js, run ls ~/bug_bounty/ ./ and look for a matching directory. If found, use it.
  • If $ARGUMENTS is a GitHub URL but /tmp/bughunt/<basename> or ~/bug_bounty/<basename> already exists, use that.
  • Only clone if no copy exists: git clone <url> /tmp/bughunt/$(basename <url> .git).
  • If $ARGUMENTS is a local path → work from that path.
  • If empty → ask: "Which repo should I audit? Provide a GitHub URL or local path."
  • If $ARGUMENTS starts with REVISION_MODE (sent by the bug-review skill), don't start a new hunt. Open the named finding directory and close only the listed gaps: re-read the code, strengthen the PoC with controls, and update report.md and notes.md in place. If you become convinced the bug isn't real, say so in notes.md and stop.
date '+%Y-%m-%d %H:%M:%S'

Record this as hunt_start_time. Print it so the user can see when the hunt began.


Phase 1 — Architecture & Tech Stack Understanding

Goal: Understand what this project IS before looking for what's wrong with it. Elite hunters spend 20-30% of their time here.

# High-level structure
find . -maxdepth 4 -type f \
  | grep -v "node_modules\|\.git\|dist\|build\|coverage\|\.next\|__pycache__" \
  | head -100

# Package manifest — tells us language, framework, key dependencies
cat package.json 2>/dev/null \
  || cat go.mod 2>/dev/null \
  || cat Cargo.toml 2>/dev/null \
  || cat requirements.txt 2>/dev/null \
  || cat pom.xml 2>/dev/null

# Entry points
find . -maxdepth 4 \( -name "index.*" -o -name "main.*" -o -name "server.*" -o -name "app.*" \) \
  | grep -v "node_modules\|\.git\|test\|spec" | head -20

# Recent changes — what the team has been touching (recent = higher chance of bugs)
git log --oneline -30 2>/dev/null
git diff HEAD~10 HEAD --name-only 2>/dev/null | head -30

Read the README and any SECURITY.md. Read the main entry file fully.

MANDATORY — read the project's own security guidance. Many mature projects encode their security model in CLAUDE.md, AGENTS.md, SECURITY.md, CONTRIBUTING.md, or top-level docs. Read each of these end-to-end if present. They often contain explicit invariants like "all internal-only headers must be in INTERNAL_HEADERS" or "never trust X without validation." A finding that violates the maintainers' own documented invariant is the strongest possible bounty framing — it forecloses the "working as intended" rebuttal.

for f in CLAUDE.md AGENTS.md SECURITY.md CONTRIBUTING.md docs/security.md; do
  [ -f "$f" ] && echo "===== $f =====" && cat "$f"
done

Document:

  • Language + framework + version
  • Is this a library, CLI, server, or build tool?
  • What is the trust model? (Who are users? What do they control?)
  • What are the critical data flows? (auth, data parsing, file access, subprocess)

Install tools if available:

# Check for Semgrep (semantic pattern analysis — far better than raw grep)
which semgrep 2>/dev/null && echo "semgrep available" || echo "semgrep not installed"

# Check for CodeQL
which codeql 2>/dev/null && echo "codeql available" || echo "codeql not installed"

# Check npm audit for known CVEs in dependencies
npm audit --json 2>/dev/null | head -100 \
  || pip-audit 2>/dev/null \
  || cargo audit 2>/dev/null

If Semgrep is available, run it first:

semgrep --config=p/nodejs-security . --json 2>/dev/null \
  | python3 -c "import json,sys; d=json.load(sys.stdin); [print(r['path'],r['start']['line'],r['check_id']) for r in d.get('results',[])]" 2>/dev/null \
  | head -50

Phase 2 — Dependency Audit (Known CVEs)

Goal: Known CVEs in dependencies are valid bug bounty findings if the project misuses a vulnerable version.

# For Node.js projects
npm audit 2>/dev/null | grep -E "high|critical" | head -30

# Known vulnerable dependency versions
cat package-lock.json 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
pkgs=d.get('packages',d.get('dependencies',{}))
for k,v in pkgs.items():
    ver=v.get('version','?')
    print(f'{k}: {ver}')
" 2>/dev/null | head -60

# For Python
pip list 2>/dev/null | head -30
safety check 2>/dev/null | head -20

Flag any high/critical CVEs in dependencies that:

  1. Are in a version range known to be vulnerable
  2. The project actually uses the vulnerable functionality

Phases 3–6 — Sources, sinks, frameworks, auth

Work through these in order, reading the reference file for each step:

  • Phase 3, attack surface mapping. List every place attacker-controlled data enters: HTTP handlers, Server Actions, request fields, CLI args and env vars. Group them by type. Grep catalogue: references/attack-surface.md.
  • Phase 4, taint analysis. For each source, trace whether it reaches one of the ten sinks without sanitization. The sinks are command exec, dynamic code, prototype pollution, path traversal, deserialization, SSRF, SQL/NoSQL, ReDoS, template injection and hardcoded secrets. Grep catalogue: references/attack-surface.md.
  • Phase 5, framework deep dives. Run only the sections for what Phase 1 detected: Next.js, build systems, CLIs or AI SDKs. See references/framework-checks.md.
  • Phase 6, authn/authz audit. Look for missing auth checks, JWT verification gaps and IDOR via user-supplied IDs. See references/framework-checks.md.

Before investigating any candidate, check references/false-positives.md for claims that have already been disproven.


Phase 7 — Validation of Findings

This is where 76% of SAST findings are eliminated. For every suspicious pattern found:

Discount subagent confidence ratings by one full level before validating. Subagents will confidently mark hallucinated findings as "Confirmed" — they pattern-match without reading the surrounding 100 lines. Treat every subagent "Confirmed" as "Possible" until you personally read the file. Common subagent hallucinations to watch for: claiming WebCrypto AES-GCM is missing an auth tag (it isn't — subtle.encrypt embeds it), claiming a glob library doesn't anchor (most do — read compileRe/makeRe), claiming child_process.exec injection where the input is parseInt-coerced, claiming CSRF bypass without checking whether the framework's threat model actually treats that browser context as carrying credentials.

Do NOT record a finding unless you can answer YES to all four:

  1. Is the source reachable? Can an attacker actually send input to this code path? (Not in dead code, not behind multi-step auth you can't bypass)
  2. Does the taint path connect? Can you trace a continuous path from the user-controlled input to the dangerous sink without sanitization breaking the chain?
  3. Is the impact real? What concretely happens if exploited? (Not "might be bad" — what specifically can the attacker do?)
  4. Does this violate a documented invariant? Bonus, but transformative for the report: does the bug contradict an explicit rule in the project's CLAUDE.md/AGENTS.md/SECURITY.md or a load-bearing code comment? If yes, lead with that — it makes the finding nearly impossible to close as "working as intended."

For each candidate finding:

  • Read the full function, not just the matching line
  • Read every function called between source and sink
  • Look for: input validation, allowlists, sanitization functions, type coercion that breaks the exploit
  • Check if experimental/dev-only features gate the vulnerability
  • Assign: Confirmed / Likely / Possible / False Positive

Discard False Positives entirely. Only keep Confirmed and Likely.


Phase 8 — PoC Construction

For each Confirmed finding, write a minimal, runnable proof-of-concept.

Strongly prefer differential PoCs. A PoC that only shows "attack input → bad outcome" can be argued as unrelated server behavior. A PoC that shows (a) a control request that uses a similar-but-properly-handled input → benign outcome, and (b) the attack request → bad outcome side-by-side is structurally undeniable. Examples:

  • Header-filtering bug: send the missing-from-allowlist header and a header that IS in the allowlist, show only the first one survives.
  • Auth bypass: show the same protected endpoint with normal auth (403) and the bypass payload (200).
  • Cache poisoning: show victim's request before attacker's poison (clean) and after (poisoned). The diff between the two requests is the bug, isolated.

Format depends on the bug type:

For RCE / injection bugs:

// minimal-poc.js — demonstrates [Bug Name]
// Run: node minimal-poc.js
// Expected: [what should happen that proves the bug]
const exploit = async () => {
  // ...
};
exploit();

For HTTP/API bugs:

# Demonstrates [Bug Name]
# Replace TARGET with the test instance
curl -X POST https://TARGET/api/endpoint \
  -H "Content-Type: application/json" \
  -d '{"field": "<payload>"}'
# Expected response: [what proves it worked]

For build system bugs:

// malicious.config.js or turbo.json
// Place in project root and run: npm run build

If you cannot construct a working PoC, mark the finding as Likely not Confirmed.


Phase 9 — Final Report

Persist findings to disk before printing them to chat. Chat scrollback gets lost; /tmp/ gets wiped. Every confirmed finding must end up at a stable path you can hand to the user or revisit weeks later.

Layout convention

~/bug_bounty/
├── <repo>/                                           # the source clone
└── findings/
    └── <repo>/
        └── YYYY-MM-DD-<short-slug>/                  # one directory per finding
            ├── report.md      ← H1-ready writeup (the structured report below)
            ├── poc/           ← working PoC (move from /tmp into here)
            │   ├── ...        ← app code, scripts, fixtures
            │   └── run-poc.sh ← the exact commands that reproduce the bug
            └── notes.md       ← dropped candidates, FP analysis, hunt timeline

Required write steps

  1. mkdir -p ~/bug_bounty/findings/<repo>/$(date +%Y-%m-%d)-<slug>/poc
  2. Write report.md (the full report in the format below) at the root of that directory.
  3. If you built a PoC scaffold (e.g. in /tmp/), move it (not copy) into poc/ and write run-poc.sh containing the exact differential-PoC commands.
  4. Write notes.md listing every false-positive you discarded with a one-line "why FP" — this is what makes the next hunt faster.
  5. Only THEN print the report to chat, and end your chat reply with the absolute path: Saved to: ~/bug_bounty/findings/<repo>/.../

If no findings are confirmed, still write notes.md to ~/bug_bounty/findings/<repo>/YYYY-MM-DD-no-findings/ so the next hunt knows what was already checked.

Write report.md using the template and writing-style checklist in references/report-format.md. Plain, specific, first-person prose wins with triage. Then print the hunt summary and three concrete next steps.


Token Discipline

Hunts are token-expensive. These rules cut waste without cutting depth:

  1. Brief subagents to return raw findings, not reports. Don't ask for prose summaries — agents spend 30–40% of their output on boilerplate ("Let me create a comprehensive report…", severity tables, closing summaries). Demand a single markdown table OR JSONL, one finding per line, max ~10 rows, no preamble. You (the orchestrator) format the final report once.

    Example agent reply format to require:

    {"file":"path:line","snippet":"...","confidence":"Confirmed|Likely|Possible","repro":"curl ..."}
  2. Don't parallelize agents with overlapping scope. If 5 agents all grep req.headers / child_process, you pay for the same file-reads 5 times. Smarter: one agent produces a sink inventory; the others each take a single specialized file/subsystem and audit it deeply with no re-grepping.
  3. Skip optional tool-install ceremony for short hunts. Phase 1 mentions semgrep/codeql/npm-audit installs — only run those if you expect the hunt to exceed ~30 min wall-clock. For sub-30-min subagent-driven hunts, they're pure overhead.
  4. Cache between hunts on the same repo. If you're hunting the same target twice (e.g. all of Vercel's Tier 1 repos), save Phase 1 architecture output to ~/bug_bounty/.bug-hunt-cache/<repo>/phase1.md keyed by git HEAD. Reuse it next time if HEAD hasn't moved more than ~50 commits.
  5. Use Read(file, offset, limit) not cat | head. Bash returns the full file to the tool runner; Read with limits only ships the lines you asked for.
  6. Grep with wc -l before reading the full match list. If grep returns 80 matches, you almost never want all 80 in context — get the count, then re-grep with a tighter pattern or just read 3–5 representative hits.
  7. Re-use PoC scaffolds across hunts. Keep working PoC harnesses at ~/bug_bounty/.poc-scaffolds/<framework>/ (a working Next.js project, a working Express project, etc.). Copying a known-good pnpm-workspace.yaml + .npmrc + minimal app is faster than rediscovering the right install incantation each time.
  8. Don't re-read files you just wrote. Edit/Write would have errored on failure. The harness tracks state.

Expected savings if rules 1–4 are followed: ~30–45% fewer tokens for the same finding quality.


Ground Rules (Non-Negotiable)

  • Only test local clones — never against production systems, live APIs, or deployed environments
  • No data exfiltration — if you find real credentials or PII in the code, redact them and flag separately
  • PoC required — do not report a finding without a working or clearly demonstrable proof of concept
  • No AI-hallucinated reports — every finding must be traceable to specific file + line + confirmed data flow
  • Confidentiality — remind the user to keep findings private until the vendor responds (Vercel: 2-year NDA)
  • Use HackerOne alias email (h1username@wearehackerone.com) when creating any test accounts

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.