elementalsouls/recon-scope-triage
Triage ASM/recon output for ownership before testing — separate the target's real assets from namespace-collision noise. Automated recon keyword-matches on the brand name, so for any target whose name is a common/dictionary word, the output is dominated by assets belonging to UNRELATED same-named companies (repos, cloud buckets, mobile apps, breach corpora, typosquats). Built from an authorized engagement where an ASM report's "Criticals" were overwhelmingly false positives and the combo/repos/mobile/bucket lists were polluted with unrelated same-named orgs. Use at the START of any engagement, immediately on receiving any ASM/recon/OSINT dataset, BEFORE testing anything.
npx skills add https://github.com/elementalsouls/Claude-BugHunter --skill recon-scope-triage
Trigger when:
apex, summit, vertex, nova, core, orbit, pulse, unity…)The two failure modes this skill prevents:
Rule: ownership is guilty-until-proven. An asset is the target's only when a concrete ownership signal ties it to the target — never because a scanner's keyword matched.
| Recon source | How it collides | Verify ownership by |
|---|---|---|
| GitHub repos | Search matched the brand word in repo name / topic / a string | Repo owner is the org's GH org; commits from org emails; code references the org's real domains/infra. A repo named <word>-backend by a random user = noise. |
| Cloud buckets (S3/GCS) | Bucket names are a global namespace; <word>-static, <word>-data, <word>-public exist for *someone* | Bucket content references the target; bucket name correlates with a *confirmed* target subdomain (x.target.com ↔ x-public) AND content matches; ACL/owner metadata. Generic content (other-language, other-industry) = not theirs. |
| Mobile apps | Store search matched the brand word in app name / package | Publisher account = the org; package reverse-DNS = an owned domain (com.<owneddomain>.app); dev cert; app calls owned API hosts. Mature ASM tools emit an "apps_accepted=0" / ownership-confidence field — read it. |
| Breach corpora / combos | Email local-or-domain contains the brand word | Exact owned-domain match only (@target.com), not @<word>group.com / @something<word>.com. A different domain that contains the word is a different org. |
| Typosquats | Generated permutations of the name | These are *defensive*/brand-protection findings, not offensive scope — note and move on. |
| Stack/forum/paste hits | Brand word in body | Body references the target's real domain/subdomain/employee/secret. Ownership-confidence < threshold = drop. |
Automated .env / .git / actuator / admin-panel "Criticals" are overwhelmingly soft-404s: SPA/framework catch-alls returning HTTP 200 (or 403) for *every* path. Verify EACH before believing it:
# the "finding"
curl -s -o /tmp/a -w "%{http_code} %{size_download}\n" https://host.target.com/.env
# a junk control on the same host
curl -s -o /tmp/b -w "%{http_code} %{size_download}\n" https://host.target.com/zzz-nonsense-$RANDOM
# identical byte length / body → FALSE POSITIVE (catch-all), discard
cmp -s /tmp/a /tmp/b && echo "SOFT-404 false positive" || echo "differs — investigate"
Real exposures have a content-type + signature that differs from the catch-all (.git/config starts [core]; .env has KEY=value; phpinfo has the XHTML-transitional doctype + PHP Version). A physical .php/phpinfo.php that returns a *bigger/different* body than the junk control is the real-vs-soft-404 tell.
loot/quarantined_<source>.txt) so it's auditable that you saw them and chose not to target them.user@<word>company.com is a different company's employee.For a target whose brand is a common word, expect the bulk of automated "owned" assets to be collisions:
<word>group.com, <region><word>.com).On a real engagement against a dictionary-word brand, after clearing this noise the only genuinely-owned high-severity finding was discoverable solely by manual tradecraft (a JS-bundle → API discovery, see hunt-spa-api) — it was nowhere in the hundreds of scanner "Criticals." Triage-first is what made the engagement productive instead of a goose chase.
triage-validation — asset-ownership triage (this skill) precedes finding-validity triage (the 7-Question Gate). Ownership first, then validity.redteam-mindset — "aggressive default" means probe every *owned* live surface; this skill defines which surfaces are owned so persistence isn't wasted on collisions.hunt-spa-api — once an API host passes ownership triage, this is how you test it.offensive-osint / osint-methodology — feed ownership anchors (verified domains, tenant brand, dev accounts) from OSINT into this triage.Take elementalsouls/recon-scope-triage from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.