Skip to content

feat(arsenal): subdomain takeover detection built-in - #134

Merged
jmagly merged 3 commits into
elder-plinius:mainfrom
2alf:feat/subdomain-takeover-tool
Jul 31, 2026
Merged

feat(arsenal): subdomain takeover detection built-in#134
jmagly merged 3 commits into
elder-plinius:mainfrom
2alf:feat/subdomain-takeover-tool

Conversation

@2alf

@2alf 2alf commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Hello again!

Why

The prompts already tell the agent to flag "subdomain takeover candidates (CNAME → unclaimed resource)", but no tool actually checked for them. This adds the missing instrument. Keyless, pure-Node, works out of the box like dns_lookup.

How

New subdomain_takeover_check built-in (recon):

  • Resolves the target's CNAME.
  • Checks if the CNAME target still resolves (dangling = strong signal).
  • Fetches the live body via the scope-gated targetFetch and matches known unclaimed-resource fingerprints (S3, GitHub Pages, Heroku, Azure, Fastly, Netlify… 15 services).
  • Returns a conservative verdict ::: confirmed / potential / none.

Notes:

  • Decision logic is isolated in takeover.ts (classifySubdomainTakeover) → fully unit-tested, no network.
  • Conservative: a live SaaS CNAME is only ever potential, never a false confirmed.
  • Added to the Recon operator toolkit; arsenal count bumped 108 → 109 in lockstep (README + verify-claims + count-honesty test).

Verify:

npm run build

node -e "import('./dist/arsenal/index.js').then(async m=>{const t=m.BUILTIN_TOOLS.find(x=>x.name==='subdomain_takeover_check');console.log((await t.handler({parameters:{target:process.argv[1]}})).output)})" blog.example.com

Confirmed path is covered end-to-end with DNS+fetch mocked in the test suite.

Commands run:

  • npm run typecheck -> pass
  • npm test -> pass
  • npm run doctor -> pass (optional-tool warnings only, 0 blockers)
  • npm run verify-claims -> CLAIM 4 updated to 109 tools in lockstep, no bench artifacts changed
  • New logic is I/O-free and unit-tested (classifySubdomainTakeover); live-verified against author-owned domains

If anything needs to be looked at and fixed please ping me.

2alf added 3 commits July 29, 2026 17:09
Pure, I/O-free detection logic split into src/arsenal/takeover.ts so it is fully
unit-testable without DNS or network:
- TAKEOVER_FINGERPRINTS: curated CNAME + unclaimed-resource-body signatures for 15
  high-frequency services (S3, GitHub Pages, Heroku, Azure, Fastly, Shopify, Netlify, ...)
- classifySubdomainTakeover(): conservative verdict (confirmed / potential / none) driven by
  a dangling CNAME and/or a service body fingerprint; no cross-service false matches
- renderTakeoverReport(): human-readable output block
… count 108->109

- New keyless, self-contained built-in tool 'subdomain_takeover_check' (recon): resolves the
  CNAME, checks whether the target still resolves (dangling), fetches the live body via the
  scope-gated targetFetch, and classifies via classifySubdomainTakeover. Emits a real finding.
- Added to the Recon operator's default toolkit so the swarm can reach it (operator-toolkits
  coverage invariant).
- Bumped the advertised arsenal size 108 -> 109 in lockstep across the count-honesty test,
  README, and verify-claims (73 adapters + 36 built-in).
…cked DNS/fetch e2e)

- classifySubdomainTakeover decision matrix: confirmed via body fingerprint, confirmed via
  dangling nxdomain-prone CNAME, potential (known service, no confirmation), potential
  (dangling unknown), none (no CNAME / resolves clean), and no cross-service false matching
- renderTakeoverReport output shape
- end-to-end handler test with DNS + fetch mocked, driving the confirmed S3 path
@jmagly
jmagly merged commit 44e7c21 into elder-plinius:main Jul 31, 2026
1 check passed
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.

2 participants