Skip to content

feat(skills): add bug-chaining, johnwick, jsmax, pii-hunter, omni-kil… - #172

Open
lucifer0xf wants to merge 202 commits into
awarexone:mainfrom
lucifer0xf:feature/add-new-skills
Open

lucifer0xf wants to merge 202 commits into
awarexone:mainfrom
lucifer0xf:feature/add-new-skills

Conversation

@lucifer0xf

@lucifer0xf lucifer0xf commented Oct 5, 2026 •

Copy link
Copy Markdown

Add bug-chaining, johnwick, jsmax, pii-hunter, omni-killchain, bugcrowd-reporting skills

Summary

  • Adds 6 specialized agent skills (bug-chaining, johnwick, jsmax, pii-hunter, omni-killchain, bugcrowd-reporting) into the skills/ directory.
  • Expands end-to-end hunting workflows, covering vulnerability chaining, client-side JavaScript analysis, PII identification, multi-vector kill chains, and platform-specific reporting.
  • Includes modular reference guides, methodology checklists, and structured reporting templates for standardized vulnerability documentation.

Type

  • Bug fix
  • New feature / scanner module
  • Methodology improvement
  • Documentation
  • False positive reduction

Test Plan

  • No hardcoded targets, API keys, or real domain names in reference files or templates
  • Verified all SKILL.md files follow standard agent skill frontmatter and formatting conventions
  • Verified directory structures and markdown cross-links resolve properly

Related Issue

Closes #

Evidence (for methodology changes)

  • Bug Chaining & Killchains: Follows standard vulnerability escalation workflows (e.g., Low/Info findings elevated via CSRF/CORS/SSRF to Account Takeover or RCE as documented across OWASP and HackerOne Hacktivity disclosures).
  • JS Mining & PII Analysis: Aligns with standard static analysis methodologies for discovering exposed API endpoints and sensitive data handling in client-side bundles.
  • Bugcrowd Reporting: Conforms to Bugcrowd VRT (Vulnerability Rating Taxonomy) severity guidelines and disclosure best practices.

shuvonsec and others added 30 commits April 7, 2026 16:36
…Solana audit

New skill (meme-coin-audit), agent (token-auditor), command (/token-scan), and
automated scanner (token_scanner.py) for detecting rug pull vectors in EVM and
Solana meme coins. Covers hidden mint, honeypot, fee manipulation, LP drain,
bonding curve exploits, authority retention, fake renounce, and sandwich
amplification. Includes 3 web3 knowledge files, 13 new grep blocks, and 39 tests.
…art fix, new TODOs

- README badge: v3.0.0 → v4.1.0
- README stats: 13 commands/7 agents/8 skills → 14/8/9
- Quick Start: add install_tools.sh as Step 1 (was missing, caused /recon to fail cold)
- .gitignore: add hunt-memory/ (full URL history, should never be committed)
- TODOS.md: add TODO-6 (auto-memory at session end), TODO-7 (memory GC), TODO-8 (4 test gaps)
…unt + autopilot

- memory/schemas.py: add make_session_summary_entry() — builds auto-logged journal entry
  with vuln_class=session_summary, result=informational, tags=[auto_logged, session_summary]
- memory/hunt_journal.py: add log_session_summary() — calls make_session_summary_entry(),
  silently swallows errors (non-fatal, must never crash the hunt loop)
- agents/autopilot.md: auto-log at Session Summary step after every session
- commands/hunt.md: auto-log at session end
- tests/test_hunt_journal.py: 11 new tests covering schema, non-fatal failure, coexistence
  with manual entries, query filtering
- TODOS.md: mark TODO-6 resolved

Closes TODO-6. Memory flywheel now starts on day 1 without manual /remember.
…stand

- Added "What Is This?" section explaining bug bounty for newcomers
- Explained what Claude Code is before assuming knowledge
- Rewrote vulnerability class table with plain explanations (not just names)
- Split commands into "Core 4" and "Power Commands" so beginners know where to start
- Rewrote "How It Works" diagram with plain labels (map it / test it / write it)
- Condensed older release notes under a collapsible section
- Simplified Golden Rules to plain English
- Fixed: agent count 7 → 8, added token-auditor
FAQ.md:
- 20 questions covering: what is bug bounty, what is Claude Code, do I need to be
  a hacker, safety of autopilot, how memory works, Burp Suite, web3/token-scan,
  troubleshooting, updating, reporting bugs

TERMS.md:
- Authorization requirement (only test in-scope targets)
- User responsibility for every request sent
- No-liability disclaimer
- Autonomous mode warning
- Prohibited uses list
- MIT license reference

README: added FAQ and Terms links to nav bar
Add: IP and CIDR target support (hunt.py + recon_engine.sh)
Improve: Burp Suite-style self-contained HTML report generator
Add: MFA bypass and SAML/SSO checks to vuln_scanner.sh
…sification (awarexone#16)

- Orphan process kill: Popen + os.setsid + killpg(SIGKILL) in cve_hunter.py, zero_day_fuzzer.py, hunt.py
- macOS timeout compat: gtimeout fallback + passthrough wrapper, ~/go/bin in PATH
- Emergency subdomain merge on EXIT trap in recon_engine.sh (prevents 0-finding scans on kill)
- Dalfox 900s global timeout + URL dedup by (scheme, netloc, path, param_keys)
- Report severity now inherited from templates — SQLi/RCE classified critical not medium
- set -euo → set -uo: fixes early exit breaking || true fallback patterns

Co-authored-by: venkatas <your-github-email@example.com>
- validate.py: CVSS 3.1 → 4.0 full scorer, 11 base metrics, 54-entry macro-vector table, FIRST.org link
- tools/recon_adapter.py: auto-detects nested vs flat recon output, unified ReconData, --migrate flag
- agents/report-writer.md: CVSS 4.0 metric descriptions and example vectors
- TODOS.md: TODO-2/3/4/5 marked resolved

Co-authored-by: Paebak <Matthew_Downs@users.noreply.github.com>
…hrome MCP, source code mode

Fixes awarexone#18 — /resume conflicted with Claude Code's built-in /resume command.
Addresses awarexone#17 — session isolation, multi-target, vague results, token use, Chrome MCP, local repo.

Changes:
- commands/resume.md → commands/pickup.md (renamed)
- CLAUDE.md: updated command table, added conflict warning note
- README.md: all /resume references → /pickup
- agents/autopilot.md: /resume → /pickup
- commands/autopilot.md: session isolation warning, --quick flag, multi-target via targets.txt
- commands/hunt.md:
  - Session isolation guidance (one session per target)
  - Multi-target support (targets.txt)
  - --source-code mode docs (local repo or GitHub URL)
  - --chrome mode docs (Chrome MCP integration)
  - Anti-vague rule: how to demand specific curl commands instead of generic advice
- commands/remember.md: /resume → /pickup

Closes awarexone#18
Closes awarexone#17
…d by Claude Code slash commands

- Deleted tools/cve_hunter.py → use /intel instead
- Deleted tools/report_generator.py → use /report instead
- Deleted memory/hunt_journal.py → use /remember instead
- Deleted associated tests
- Stubbed out generate_reports() and run_cve_hunt() in hunt.py with warning messages
- Removed HuntJournal import from memory/__init__.py
- Updated CLAUDE.md, commands/hunt.md, agents/autopilot.md to remove references
Installation Verification stops after first found tool due to `((INSTALLED++))` bash pitfall
Resolves TODO-7 (memory GC / rotation) and partially resolves TODO-8
(concurrent-write + disk-full coverage).

- memory/rotation.py: size-based JSONL rotator under fcntl.LOCK_EX
  (10 MB cap, keep 3 backups). Wired into AuditLog.log() and
  PatternDB.save() so audit/pattern logs stop growing unbounded.
- tools/memory_gc.py + /memory-gc command: inspect, rotate, or purge
  hunt-memory backups across the tree.
- tests/test_rotation.py: 22 tests covering rotation primitives,
  auto-rotation in writers, multi-process concurrent writes (with and
  without rotation), and disk-full OSError propagation.
- README: refreshed to v4.2.0, swapped ASCII diagram for Mermaid,
  promoted $BUG token CA to a shields badge linking to pump.fun,
  stripped redundant section dividers, restructured footer.
- CLAUDE.md / CHANGELOG / TODOS: updated counts (15 commands), added
  v4.2.0 release notes, marked TODO-7 resolved and TODO-8 partial.
Resolves the final open item in TODO-8.

PatternDB.save() previously re-read the entire JSONL file on every call
to detect duplicate (target, vuln_class, technique) tuples. At 10k
entries this pegged a CPU for 5+ minutes per insertion pass — confirmed
live by the new perf test.

Fix: lazy in-memory dedup index of (target, vuln_class, technique) keys.
Populated on first save() (so opening a read-only DB stays free) and
updated after each successful append. Cross-process dedup is now best-
effort — two independent instances can each pass the dedup check before
either writes — but the cost is one wasted JSONL row, not correctness.

- memory/pattern_db.py: _dedup_keys set + _load_dedup_keys + _dedup_key
- tests/test_pattern_db.py::TestPatternPerformance: 4 new tests covering
  the < 5 s perf bound at 10k, dedup correctness at scale, lazy-load via
  reopen, and corrupted-line resilience (suggested by python-reviewer).

10k saves: ~5 min → 2.14 s. Full suite: 184/184 in 2.93 s.
tests/test_recon_adapter.py has been silently uncollectable since the
file was renamed away from the original layout — pytest aborted the
file with ImportError before any of its 31 tests could run. The 31-test
gap was masked by --ignore=tests/test_recon_adapter.py being baked into
local invocations.

Added ReconAdapter to tools/recon_adapter.py with:
- read accessors over the subdir-nested layout written by recon_engine.sh
  (subdomains/all.txt, live/urls.txt, live/httpx_full.txt, urls/all.txt,
  urls/with_params.txt, urls/js_files.txt, urls/api_endpoints.txt,
  urls/sensitive_paths.txt, js/potential_secrets.txt,
  params/interesting_params.txt, exposure/config_files.txt)
- graphql extraction (prefer urls/graphql.txt, otherwise filter URLs by
  /graphql, /gql, /v1/graphql, /api/graphql hints)
- live-host fallbacks: live/urls.txt → live/httpx_full.txt → root
  httpx_full.txt (extracts the URL from "URL [200] [type]" lines)
- get_resolved_subdomains: prefers subdomains/resolved.txt, falls back
  to subdomains/all.txt
- summary() with the 6 counts brain.py uses
- normalize() that creates priority/, api_specs/, urls/graphql.txt,
  subdomains/resolved.txt, priority/prioritized_hosts.json,
  priority/attack_surface.md — idempotent, never overwrites

The original load_recon / ReconData API (single-file canonical format)
is untouched. Distinct API surface, distinct file layout.

Suite: 184 → 215 tests, all passing in 3.60 s.
Inline rotation in AuditLog/PatternDB only fires when a write would
exceed the cap. Long sessions that wrote a lot but never crossed the
cap mid-session never got cleaned up — until now.

Adds a project-scoped Stop hook in .claude/settings.json:

  [ -f tools/memory_gc.py ] && python3 -m tools.memory_gc --rotate \
    >/dev/null 2>&1 || true

The guard makes it a silent no-op if the cwd isn't the repo root or
the script is missing, so it's safe to ship in the checked-in settings
file. async: true keeps it from blocking session shutdown. timeout: 30
caps the worst case.

Updates commands/memory-gc.md to document the two auto-rotation
trigger points (write-time + session-end).

Validated: pipe-test runs exit 0 in repo + outside repo; jq -e
schema check on the settings file passes.
…scanner collect (awarexone#21)

tests/test_credential_store.py and tests/test_token_scanner.py both do
``from tools.credential_store import CredentialStore`` (and similar),
which requires tools/ to be an importable Python package. Without
tools/__init__.py, pytest errors out during collection:

    ModuleNotFoundError: No module named 'tools.credential_store'

55 passing tests disappear as a result. Adding a trivial package
marker brings them back (total: 191 → 242 passing under
``PYTHONPATH=. pytest tests/``).

Note: tests/test_recon_adapter.py still fails to import — the test
expects an OO ``ReconAdapter`` class, but tools/recon_adapter.py only
exposes functional APIs (``load_recon``, ``normalize_to_nested``).
That is a module/test API drift to resolve in a separate PR; this
change does not touch it.

Co-authored-by: Venkata Satish <your-github-email@example.com>
…rexone#19)

LLMClient._auto_detect() iterated PROVIDER_PRIORITY in fixed order
["ollama", "claude", "openai", "grok"]. Users who set only a cloud
API key (e.g. ANTHROPIC_API_KEY) and don't run Ollama still hit the
Ollama probe first — it either fails slowly or succeeds with the
wrong model.

Re-order so providers whose API key env var is set are probed first,
then the remaining providers keep their original relative order.
Ollama stays as the final fallback when no keys are set.

Adds unit tests covering: ANTHROPIC_API_KEY jumps claude to front,
two cloud keys front-loaded together, no keys falls through to
default priority, and key-set-but-provider-unavailable fallback.

Co-authored-by: Venkata Satish <your-github-email@example.com>
…ne#20)

scripts/full_hunt.sh ran katana at depth 5 with no timeout wrapper —
content-heavy targets (news, video, infinite calendars) could hang the
entire hunt. Depth is also out of step with agents/recon-agent.md and
commands/recon.md which both specify -d 3.

tools/recon_engine.sh had no katana step at all, so active crawling was
only available through the standalone full_hunt.sh, not the primary
recon pipeline invoked by hunt.py / agents / /recon command.

Changes:
- tools/recon_engine.sh: add katana active crawl in Phase 4 (URL
  Collection), 5 min cap, top 50 live hosts, depth 3, -kf all.
  Uses the timeout() shim already installed in this file.
- scripts/full_hunt.sh: install the same gtimeout/passthrough shim as
  recon_engine.sh and vuln_scanner.sh, wrap katana with 5 min cap,
  reduce depth 5 → 3, add -kf all, guard empty-file cat.

Co-authored-by: Venkata Satish <your-github-email@example.com>
…e#31)

* fix: stabilize pytest collection and tool imports

* fix(recon): detect ProjectDiscovery httpx vs Python httpx and fail fast

Brew installs `python-httpx` at /opt/homebrew/bin/httpx (the unrelated REST
client CLI), and on many macs it precedes ~/go/bin on PATH despite the
existing `export PATH="$HOME/go/bin:..."`. The Python httpx CLI silently
rejects ProjectDiscovery flags like `-silent` and `-tech-detect` with
"No such option" and exits 0, producing an empty httpx_full.txt and
zero live hosts — the operator only notices much later when the rest of
the pipeline finds nothing to probe.

Resolution:

- Add `_resolve_pd_httpx()` helper that walks ~/go/bin, /opt/homebrew/bin,
  /usr/local/bin, and `command -v httpx` and picks the first binary
  whose `-version` output contains the literal "projectdiscovery"
  substring. Falls back to the bare `httpx` token so existing
  command-not-found error paths still fire.
- Export `HTTPX_BIN` and replace the bare `httpx -l ...` invocation with
  `"$HTTPX_BIN" -l ...` in the live-host probe block.
- Print a one-line warning + install hint to stderr if no PD binary is
  found anywhere — the operator gets actionable feedback instead of a
  silent empty output file.

Verified: bash -n clean. Smoke-tested in the originating fork against a
target with both binaries on PATH; the right one is picked even when
Brew's path comes first.

* fix(brain): drop sqlmap-tagged false-positive rows in candidate collection

sqlmap_results.txt's CSV format carries a Note column that explicitly
labels candidates as "false positive or unexploitable" when level/risk
testing concluded the parameter is not injectable. The previous
candidate-collection logic in `_collect_candidate_findings` passed every
non-empty sqlmap line into `triage_finding()`, where the 7-Question Gate
prompt would rationalise an answer per question — sometimes producing
intermediate "Q1: YES" reasoning before settling on the correct DROP
verdict.

Two visible symptoms before this fix:

1. The streamed gate output in the live log shows the model agreeing
   that a sqlmap-flagged FP "could be exploitable" before later changing
   its mind. Operators reading along get confused.
2. `findings/<target>/brain/auto_triage.md` lists every sqlmap FP as
   `[UNKNOWN] [sqlmap] http://...,GET,d,S,false positive or unexploitable`
   — pure noise that wastes manual-review time.

Fix: in `_is_noise_finding_line`, drop any line containing the literal
"false positive or unexploitable" substring, and also drop the literal
sqlmap CSV header line. Both are deterministic strings sqlmap writes
itself, so there's no risk of suppressing real findings.

Verified observed both symptoms on a real engagement (3-domain VAPT
sweep, 2026-05-04). After the fix, auto_triage.md is empty for clean
sqlmap runs and the gate output no longer rationalises sqlmap negatives.
py_compile clean.

---------

Co-authored-by: Venkata Satish <your-github-email@example.com>
…rity

Closes awarexone#25 (proposal evaluation), awarexone#28 (free-account wording), awarexone#29 (domain
list support), awarexone#30 (Caido MCP integration).

- tools/recon_engine.sh + tools/hunt.py: accept a path to a text file of
  hosts as the target. Skips subdomain enum entirely — for programs without
  wildcard scope where enum is wasted work. Output dir derives from the
  basename so multiple lists don't collide. Tests in
  tests/test_hunt_target_types.py.
- commands/recon.md: document the new list and CIDR forms.
- mcp/caido-mcp-client/: new integration mirroring the Burp MCP client,
  wraps the community caido-mcp-server (42 tools, auto-redacts auth
  headers). README has full PAT/OAuth setup, troubleshooting table, and
  notes on running Burp + Caido side-by-side.
- rules/hunting.md: prepend rule #0 — engagement context. States the
  operator is an authorized hunter on public bounty programs with
  safe-harbor terms, frames the role as hunter-not-pentester, keeps hard
  limits explicit (out-of-scope, real-user data, DoS, social-engineering).
  Addresses the most concrete actionable point from issue awarexone#25.
- README.md: fix misleading "free account" wording — Claude Code itself is
  free to install but actually using it requires Pro/Max or API billing.
  Also list Caido alongside Burp in the MCP comparison row.
…lei phase (awarexone#36)

- New commands: /arsenal, /bypass-403, /cloud-recon, /param-discover,
  /scan-cves, /scope-aggregate, /secrets-hunt, /takeover
- New tools: external_arsenal.sh registry, scope_aggregator, secrets_hunter,
  takeover_scanner, cloud_recon, param_discovery, bypass_403, cve_scan
- Auth session support: tools/auth_session.py + _auth_helper.sh + tests,
  schemas.py session_id field, docs/auth-sessions.md
- recon_engine.sh: optional nuclei phase; vuln_scanner.sh refinements
- skills: security-arsenal METHODOLOGY_CHEATSHEET + REFERENCES, updates to
  bb-methodology, bug-bounty, triage-validation, web2-vuln-classes
- Drop unused logo SVGs; ignore nested claude-bug-bounty/ clone

Co-authored-by: Shuvonsec <shuvonsec@Shuvonsecs-MacBook-Pro-2.local>
- Drop $BUG/pump.fun badge and "CA: ..." link from the header.
- Bump version badge to v4.3.0; commands count 15 → 23.
- Replace removed badge with PRs-welcome.
- New "Recon Toolkit (v4.3)" section documenting the 8 new wrappers.
- New v4.3 entry under What's New covers auth-aware hunting +
  external_arsenal.sh registry + methodology cheatsheet.
- Add auth-aware row to the Before/After table.
awarexonedev and others added 27 commits September 22, 2026 04:26
Render the recovery line as a lime panel matching the website CTA color.
Closes the docs/CAPABILITY-GAPS.md gap "No automatic PoC capture
(screenshot/HAR/video) for reports". The toolkit could find bugs but left
the hunter to hand-assemble proof; this produces a reproducible evidence
bundle laid out exactly as skills/report-writing + commands/report.md expect.

tools/poc_bundler.py — two modes:
- capture <url>: perform the request live via the repo's SSRF-guarded
  safe_http.safe_urlopen and bundle it.
- from-request <req.txt> [--response resp.txt]: build a bundle offline from
  a saved raw request (e.g. copied out of Burp) — no network.

Emits under findings/<target>-<class>/evidence/<id>/:
  request.http, response.http, repro.sh (curl), evidence.har (HAR 1.2),
  optional screenshot.png (best-effort httpx), evidence.md (report-ready),
  bundle.json (manifest + full-response SHA-256).

Security (senior defaults):
- Secrets redacted by default — Authorization/Cookie/Set-Cookie/API keys are
  masked in every artifact so the bundle is safe to paste into a report;
  repro.sh stays runnable by referencing each secret via an env var
  ($AUTHORIZATION, $COOKIE, ...) instead of hardcoding it. --no-redact opts out.
- PUT/DELETE/PATCH refused without --confirm-unsafe (mirrors the autopilot
  SafeMethodPolicy).
- Response body SHA-256 in the manifest makes evidence tamper-evident.

Design: all artifact builders, raw-HTTP parsers, and redaction are pure
functions unit-tested without a socket; only capture()/screenshot touch the
outside world. 26 tests in tests/test_poc_bundler.py. /poc command +
CLAUDE.md command-table and tools-list entries. Integrates with lead_board
(--finding-id) and the /dashboard findings view.

Co-authored-by: Shivendra-Coherent <shivendra@coherentmarketinsights.com>
Co-authored-by: Shuvonsec
…warexone#148)

Make the tool installable with `pip install agentic-bug-hunter`, exposing
`bughunter` and `bughunter-agent` console scripts, alongside the existing
clone + install.sh workflow.

- Relocate the runtime into a `bughunter/` package: agent, brain, engine,
  serve, tools/, agents/, memory/, mcp/, wordlists/. Launchers in __main__
  put the package dir on sys.path so the existing flat imports keep working.
- Keep Claude Code / OpenCode plugin assets (commands/, skills/, rules/,
  hooks/) at repo root; point the plugin manifest's `agents` at the packaged
  copy so both the CLI and the plugin resolve it.
- Redirect writable output (recon/findings/reports/targets) to a user data
  home via BUGHUNTER_HOME, falling back to the install dir when writable
  (clone) else ~/.bughunter, so read-only pip installs work unchanged.
- Add pyproject.toml, MANIFEST.in; ship package data in the wheel.
- Update install.sh engine path, pytest pythonpath, and test path anchors
  for the new layout. Full suite: 767 passed.
…ne#149)

* docs: absolute asset/doc URLs for PyPI, bump to 6.0.1

Relative <img src> and doc links only resolve on GitHub; PyPI showed them
broken. Point them at raw.githubusercontent / blob URLs so the project page
renders. Bump version for the re-upload.

* docs: add PyPI version + downloads badges to README
Added a hash to the project description for identification.
Updated project description and corrected CA address.
…portability hardening (awarexone#158)

* fix(brain): repair Groq integration — refresh decommissioned models

The Groq default model `llama-3.3-70b-versatile` and every id advertised by
`list_models("groq")` (`mixtral-8x7b-32768`, `gemma2-9b-it`, ...) passed their
Groq shutdown dates. Groq answers a retired model id with HTTP 404 on the
fixed `/openai/v1/chat/completions` path, which is exactly the reported
`404 Client Error: Not Found` — the base URL was never wrong.

- Default groq model -> `openai/gpt-oss-20b` (current production model).
- Refresh `list_models("groq")` to the current catalog; drop dead ids.
- Add `GROQ_LEGACY_ALIASES` remapping every retired id to a live gpt-oss
  model, mirroring the existing Grok/DeepSeek alias handling, so saved
  configs and `--model llama-3.3-70b-versatile` keep working.
- Turn a 404 on any OpenAI-compatible provider into an actionable error
  ("model likely retired — list current models / set BRAIN_MODEL") instead
  of a bare stack trace.
- Add tests/test_groq_models.py pinning the current defaults.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(recon): normalize URL/host/protocol and support local targets

Scanners were handed the raw CLI argument verbatim, so
`bughunter recon https://9am.io/` ran `nmap https://9am.io/` (→ "0 hosts up,
0 open ports") and wrote output to `recon/https:/9am.io`. Local targets were
also useless: `recon localhost:3000` ran public subdomain enum / crt.sh /
wayback against localhost and never probed the app's port.

Target parsing (bugs awarexone#2, awarexone#3):
- New tools/target_normalize.py: single source of truth that strips scheme,
  userinfo, path/query/fragment, trailing dot and lowercases the host, pulls
  off an explicit :port (IPv6 in brackets supported), and classifies a target
  as list / local / cidr / ip / domain. CIDR is detected before normalization
  (so /NN is not stripped) and outranks the local-prefix check.
- recon_engine.sh gains a mirror `_normalize_target` + a `--normalize-only`
  test hook, recognizes loopback / RFC-1918 / *.local as "local", scope-locks
  them (skips subfinder, crt.sh, wayback, gau) and seeds the httpx probe list
  with host:port so localhost:3000 is actually probed.
- engine.py derives the output dir from the normalized host and pins
  RECON_OUT_DIR so the shell writes exactly where Python reads.

Hardening (security, see review):
- hunt.py run_recon built a `shell=True` command with the user-controlled
  target interpolated as "{domain}" — a command-injection vector (e.g.
  domain = 'a";id;"'). Rewritten to an argv list with shell=False, passing
  TARGET_TYPE / SCOPE_LOCK through the environment instead of the command
  string. Mirrors the earlier engine.py _run_shell hardening.

Tests: tests/test_target_normalize.py covers localhost, URLs with/without
protocol, domains, public/private IPs and CIDRs, and asserts the shell
normalizer agrees with the Python one. Full suite: 811 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(recon): actionable macOS/Linux install hints for missing tools

Missing scanners previously printed "X not installed — skipping" with no way
to fix it. New tools/_dep_hint.sh maps each tool to OS-specific install
commands and recon_engine.sh routes subfinder, httpx, nuclei, gau, ffuf and
nmap warnings through it. The host's own OS is printed first; both are always
shown so a copied hint is portable.

Notable: the httpx hint uses `go install` on both OSes and explicitly warns
that `brew install httpx` pulls the unrelated Python CLI (the same trap the
PATH-resolution logic already guards against).

Also splits two combined guards ("X not installed OR no hosts") so the
"install it" hint only appears when the tool is genuinely missing, not when
there was simply nothing to scan.

Tests: tests/test_dep_hint.py asserts every named tool yields macOS+Linux
commands and that warn_missing exits 0 under pipefail.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(security): prevent path traversal via target into recon/findings dirs

A target flows into filesystem paths (recon/<target>, findings/<target>) from
the CLI and, over MCP, from an untrusted client. pathlib neither collapses
'..' nor resists an absolute component, so `recon ../../etc/x` or `recon
/etc/x` could create dirs / write recon output outside the sandbox, and the
MCP adapters could be steered into arbitrary-location reads.

- target_normalize.py: add is_safe_host() + safe_target_dirname(), a strict
  single-path-component allowlist (no '/', '\', NUL or '..').
- engine.py cmd_recon/cmd_hunt: use safe_target_dirname and REJECT unsafe
  targets — never fall back to the raw value (the fallback introduced when the
  normalizer landed was itself the traversal enabler).
- mcp/bughunter-mcp/adapters.py: add _safe_under() (resolve()+containment,
  matching the existing bughunter_get_finding check) and apply it to run_recon,
  read_recon_file (target AND relative), attack_surface and list_findings;
  pin RECON_OUT_DIR to the contained dir.
- recon_engine.sh: strip all trailing dots (match Python) and refuse an
  empty / '.' / traversal target after normalization (exit 2).

Tests: tests/test_path_traversal.py covers the normalizer, all MCP adapters
and the shell guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(security): eliminate remaining shell=True command injection in hunt.py

The earlier hardening fixed run_recon/graphql_audit and engine._run_shell, but
four sibling sinks still built shell=True command strings with the
target/domain interpolated as "{domain}" — double-quoting does not stop
$(...)/backtick substitution, so `--cve-hunt --target 'x$(id)'` (or a scope
domain from selected_targets.json) executed arbitrary commands.

- run_cve_hunt, run_zero_day_fuzzer, run_vuln_scan: argv list + shell=False.
- run_cmd: accept an argv LIST (shell=False) and use it for every
  target-derived call — ingest/next (lead_board), --tech (eol_check), and the
  wordlist curl. Plain strings are still allowed only for the fully-hardcoded
  `command -v` builtin checks.

Tests: tests/test_injection_hunt_sinks.py drives each entry point with a
`$(touch marker)` domain and asserts the marker is never created.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(security): create secret-bearing files owner-only (0600)

Two at-rest exposure issues on multi-user hosts:

- engine.save_config wrote ~/.bughunter/config.json (which can hold API keys)
  with write_text() under the process umask, THEN chmod 600 — a brief
  world-readable window on first creation. Now created 0600 atomically via
  os.open(O_CREAT, 0600) and the parent dir tightened to 0700.
- Hunt-memory files were created 0o644 (world-readable): audit.jsonl records
  request URLs that can carry tokens in the query string, and patterns.jsonl /
  rotated files hold recon data. All now created 0o600, and the memory dir is
  chmod 0700.

Tests: tests/test_memory_file_permissions.py asserts 0600 files + 0700 dir.

Note (not changed): the audit log still stores request URLs verbatim; stripping
query-string credentials before logging is recommended as a follow-up but is
deployment-dependent, so it's left as a documented recommendation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(portability): make shell scripts work on macOS (BSD) and Linux (GNU)

These constructs silently misbehave on macOS (BSD userland / bash 3.2), and
`|| true` / `2>/dev/null` hid the failures:

- grep -P (BSD grep has no Perl regex): recon_engine.sh github-org extraction
  (\K reset → grep -oE + sed) and CI/CD finding count (grep -cF); cicd_scanner.sh
  \d/\s classes → ERE ([0-9], [[:space:]]).
- date +%s%N (BSD date has no %N → emits literal 'N', breaking the /1000000 ms
  math in the timing-based SQLi checks): vuln_scanner.sh gains a portable
  _now_ns() helper (GNU date → gdate → python3 → second precision) and all five
  usage sites call it.
- bare mktemp (BSD requires a template): bypass_403.sh — all 10 now use
  mktemp "${TMPDIR:-/tmp}/bypass403.XXXXXX".
- ${vuln^^} (bash-4 only, macOS ships 3.2): full_hunt.sh uses tr instead.

Tests: tests/test_shell_portability.py guards against regressions and checks
_now_ns() returns a positive integer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Aman Qureshi <aman.qureshi@indianic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ngs (awarexone#165)

* fix(hunt): reject shell metacharacters in target (command injection awarexone#153)

What: added _validate_target gate at the top of hunt_target; rejects any
  target carrying shell metacharacters or whitespace before it reaches a
  shell=True recon/scan/cve/zero-day/graphql/lead-board command string.
  Added 3 regression tests to test_shell_injection_fixes.py.
Why: hunt.py interpolated the user-controlled target into shell=True
  strings. Double-quoting does not stop $()/backtick substitution, so a
  target like $(touch x) was executed locally (issue awarexone#153). The earlier
  path validator only blocked ../ traversal, not shell metacharacters.
Update: bughunter/tools/hunt.py (+_TARGET_DENY, _validate_target, gate in
  hunt_target), tests/test_shell_injection_fixes.py (+3 tests).
Test: python3 -m pytest tests/test_shell_injection_fixes.py -q -> 6 passed;
  PoC --target '$(touch /tmp/abh...)' --recon-only -> file NOT created.

* fix(security): patch dependency CVEs, correct mcp floor, defuse skill tokens

What: bumped requests 2.32.3->2.34.2, pytest 8.3.2->8.4.2, mcp 1.28->2.2.0;
  fixed 6 stale 'mcp>=1.28' strings across install.sh/README/docs/server/cli;
  neutralized literal instruction-override tokens in SKILL.md files.
Why: SkillsLLM scan flagged 8 pypi advisories (requests/pytest/mcp@1.28) plus
  override-phrase findings. The mcp code already uses the 2.x API
  (mcp.server.mcpserver.MCPServer) so the >=1.28 floor was both vulnerable
  and broken on 1.x; 2.2.0 fixes the CVEs and matches the code. SKILL.md is
  loaded as agent instructions, so example override phrases were reworded to
  read as data, not live directives.
Update: requirements.txt, install.sh, README.md, docs/mcp.md,
  bughunter/mcp/bughunter-mcp/{README.md,cli.py,server.py},
  SKILL.md, skills/bug-bounty/SKILL.md.
Test: python3 -m pytest -q -> 864 passed; bughunter-mcp server imports clean
  on mcp 2.2.0 (from mcp.server.mcpserver import MCPServer OK).
…#162)

The fallback branch of dep_install_hint() told users to run
./tools/external_arsenal.sh, but the repo keeps tools/ under bughunter/,
so following the hint produced "No such file or directory". This is the
same stale root-relative path that made install.sh silently skip nine
agents, except this one is user-facing: it is printed by recon_engine.sh
whenever a scanner is missing from PATH.

Resolve the script's own directory once via BASH_SOURCE and print an
absolute path, so the hint works from any working directory. Falls back
to the repo-relative path if the layout moves again and the sibling
script cannot be found.

OS-specific hints for known tools (nmap, ffuf, subfinder, amass, katana)
are unchanged.

Verified: the printed path resolves from both the repo root and an
unrelated cwd; the sourced functions still load for recon_engine.sh.
Full suite: 872 passed.
awarexone#163)

commands/recon.md and commands/hunt.md both told users to run
`bash tools/install_tools.sh` when a scanner was missing. The docs
shorten `bughunter/tools/` to `tools/`, but install_tools.sh lives at the
repo root, so the snippet failed with "No such file or directory" at
exactly the moment the user needed help.

Adds tests/test_doc_paths.py, which asserts every `sh`/`bash`/`./x.sh`
command embedded in the docs resolves to a real file under the documented
prefix convention. Verified meaningful: reverting the two-line fix fails
3 of the new tests.

Runtime-created directories such as bughunter/memory/leads/ are
deliberately out of scope — lead_board.py creates that on first ingest,
so its absence is correct rather than a broken reference.

Full suite: 907 passed.
…warexone#164)

HackerOne removed three fields from the Team type, breaking every
program-stats lookup with a GraphQL validation error:

  default_currency                       -> currency
  average_time_to_bounty_awarded         -> average_bounty_lower_amount
                                          / average_bounty_upper_amount
  average_time_to_first_program_response -> (removed, no replacement)

The replacement is a dollar range, not a duration, so the old
avg_days_to_bounty / avg_days_to_first_response keys were misleading.
They are replaced by avg_bounty_lower / avg_bounty_upper, and the
intel_engine.py program summary is updated to match.

Verified live against the shopify, gitlab and uber public programs.
Full suite: 861 passed.
Adds requesty as an opt-in OpenAI-compatible gateway for standalone bughunter, wired the same way as OpenRouter: provider init, chat dispatch, default model, curated model list, setup option 11, providers table, CLI choices, saved key loading, config example, README and CHANGELOG. REQUESTY_BASE_URL optionally overrides the base URL (for example the EU region). Requesty is not added to PROVIDER_PRIORITY.
…oud (awarexone#161)

* fix(install): resolve split repo layout, anchor to script dir, fail loud

Three related defects made `install.sh` silently install less than it
claimed to:

1. agents/ lives under bughunter/, but copy_files was called with the
   root-relative glob "agents/*.md". A glob that matches nothing is
   passed through by bash as a literal string, so the loop skipped it
   and the install still exited 0 — 9 agents went missing on every
   harness without a single warning. The same applied to the mcp/ and
   tools/ references.

2. All source paths were relative to the cwd, so running the script by
   absolute path from anywhere else copied nothing.

3. copy_files/copy_tree_items reported success even when they copied
   zero files, which is what hid (1) in the first place.

Fixes:
- Anchor to the script's own directory so it runs from any cwd.
- resolve_src() picks the first existing candidate per directory, so the
  mixed root/bughunter layout is declared in exactly one place.
- copy_* now count what they copied and return 1 with a stderr warning
  when a glob matches nothing.

Verified: 10/10 agents now install from an unrelated cwd, and a
deliberately empty agents/ dir exits 1 with a warning instead of
reporting success.

* test(install): cover layout resolution, cwd anchoring, empty-glob guard

Locks in the previous fix with a regression suite that drives the real
install.sh end to end. Verified meaningful by reverting install.sh to its
pre-fix state: 11/11 tests fail there, 11/11 pass with the fix.

Covers:
- agents/skills/commands install when invoked from an unrelated cwd, and
  that re-running is idempotent
- a deliberately empty source dir exits non-zero with a warning on stderr
  instead of printing "Done" — the exact failure mode that hid the bug
- copy_files/copy_tree_items each reject a glob that matched nothing
- resolve_src prefers the first existing candidate, falls back otherwise
- static guards: no bare root-relative `agents/*.md`, every resolved var
  actually consumed, and the cwd anchor declared before the --agent
  dispatch (a bare BASH_SOURCE check passes even on the pre-fix script,
  which only anchored the standalone path)

Also drops TOOLS_SRC from install.sh: `tools/` is never read as a path by
that script, so the variable was dead code implying a guarantee that did
not exist.

Full suite: 872 passed.
Co-authored-by: Cursor <cursoragent@cursor.com>
…xone#170)

Separate discovery from validation so no finding reaches a report without a
deterministic, non-AI oracle confirming it against the live target.

- verifiers: tools/verifiers/ library (redirect, sensitive-file, auth-bypass,
  sqli error+timing, idor two-identity, oob ssrf/xxe/rce, dom-xss) each
  returning VerifyResult(confirmed, trace); REGISTRY + verify_finding dispatcher
- validator gate: tools/validate_core.py non-tty verify_finding_programmatic
  encoding kill-signal / chain-required / Q8-identity tables as code;
  validate.py --auto wrapper
- report gate: brain.write_report + hunt.py refuse any finding that is not a
  verified validated_finding with linked evidence; agent._classify_obs emits
  candidate leads, never direct findings
- swarm: fcntl-locked + adjudicated lead_board; tools/swarm.py coordinator fans
  leads out to ephemeral per-lead workers (ThreadPoolExecutor, per-worker
  session+scope); hunt.py --swarm flag
- llm skills: skills/llm-redteam + skills/agentic-app-audit; expanded
  llm_redteam corpus (multi-turn, cross-lingual, cipher, Sneaky Bits
  token-smuggling); unified ASI01-ASI10 canonical mapping; commands/llm-app-audit
- benchmark: tests/benchmark/ FLAG{} canary target + precision/recall/FP
  scorer; tests/test_benchmark.py smoke test (recall=1.0, fp_rate=0.0)

Co-authored-by: Cursor <cursoragent@cursor.com>
@shuvonsec
shuvonsec force-pushed the main branch 3 times, most recently from 9efc2d0 to fb51a54 Compare October 8, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.