anirudhbiyani/findmytakeover/dangling-dns-finder
Claude Code and agent skill by anirudhbiyani/findmytakeover
- community
Checking that the SKILL.md file is still in the repository.
Detect dangling DNS records and subdomain-takeover risks across a multi-cloud environment by running the findmytakeover tool. Use whenever the user wants to find dangling domains/records, stale CNAMEs, subdomain takeover exposure, orphaned DNS entries, or audit their DNS zones for records pointing at deleted cloud resources — dead load balancers, released public IPs, deleted S3 buckets/CloudFront/App Service, or expired SaaS targets (GitHub Pages, Heroku, Shopify...). Triggers on "dangling domains", "dangling DNS", "subdomain takeover", "audit my DNS", "find stale/orphaned DNS records", "dead CNAMEs", "broken MX/SPF", asking what's safe to delete, or setting up a daily/CI scan with alerts. Covers AWS (incl. GovCloud), Azure (incl. Azure Government), GCP, Cloudflare and Oracle Cloud, using read-only access the user already has.
Install
npx vskill@latest install anirudhbiyani/findmytakeover/dangling-dns-finderSKILL.md
Dangling DNS Finder
Find DNS records that point at infrastructure that no longer exists — the classic subdomain-takeover setup. A CNAME to a deleted ELB or S3 bucket, or an A record to a released cloud IP, can be reclaimed by someone else and used to serve content under the user's domain.
This skill drives the findmytakeover tool. It enumerates every DNS record and every live infrastructure endpoint across the configured accounts, then reports records whose target is in none of them. Third-party SaaS targets are checked for NXDOMAIN (and optionally an "unclaimed site" page). No wordlists, no guessing.
Do not write your own scripts to enumerate DNS or probe endpoints — the tool collects both sides and diffs them. Your job is to configure it, run it, and interpret the JSON. The one exception is re-checking a single record with dig right before remediation (step 5).
Prerequisites
- The tool. Use whichever is available, in this order:
findmytakeover --versionalready works → use it.- Inside a checkout of the repo →
pip install .(Python 3.12+). - Otherwise → the wheel from the latest GitHub release:
gh release download --repo anirudhbiyani/findmytakeover --pattern '*.whl' then pipx install ./findmytakeover-*.whl. (pipx install findmytakeover works too once the version is on PyPI.) Or the Docker image, with the config and cloud credential directories mounted read-only. Below, findmytakeover means whichever of these you ended up with.
- Read-only credentials already working in the local CLIs. The tool never
logs in for the user:
- AWS —
ViewOnlyAccess+SecurityAudit(or an assumable read-only role) - GCP —
Viewer(Application Default Credentials, or a service-account key) - Azure —
Reader(az login, or tenant/client/secret) - Cloudflare — read-only API token (
CLOUDFLARE_API_TOKEN) - Oracle (OCI) —
read/inspect(~/.oci/configDEFAULT profile)
Workflow
1. Configure
The tool reads a YAML config (findmytakeover.config in the repo is the annotated example; pass another with -c). Enable only the providers the user has. For each, set enabled: true and pick credentials:
credentials: default— the local CLI's session, with accounts / projects /
subscriptions auto-discovered. Simplest; prefer it.
- Otherwise an IAM role name (AWS), a service-account JSON path (GCP), or a
tenant/client/secret mapping (Azure), with accounts: listed explicitly.
Each provider appears under both dns: and infra:. A record can only be judged against inventory that was collected, so enable infra for every provider that could own a target, not just the one hosting the zone.
Government clouds:
- AWS GovCloud — no setting; the partition comes from the profile's region
(us-gov-west-1 / us-gov-east-1).
- Azure Government — add
cloud: AzureUSGovernmentto the Azure block.
exclude: takes IP ranges (CIDR, v4/v6) and domains. A domain matches itself and its subdomains, not substrings.
Confirm the scope (providers, accounts, exclusions) with the user before running — wrong account scope is the main source of false positives. When showing the config, never echo client secrets, tokens or key paths back.
2. Run
- Read
findings.json, not the console. Each finding hasrecord,
record_type, target, dns_provider, account, target_owner, saas_service, dns_status, http_status and confidence.
-d dump.csvsaves the raw DNS + inventory that was diffed. Use it when a
known-good record shows up.
--verify-httpfetches fingerprinted SaaS subdomains to match the
provider's "no such site" page. It sends requests to the user's hosts, so ask first. It confirms takeovers DNS alone can't (most SaaS wildcard DNS).
--no-verify-dnsmakes no lookups at all, for offline or locked-down runs.- An NXDOMAIN only counts if public resolvers (1.1.1.1, 8.8.8.8) don't find
the name either, so a VPN's split-horizon DNS can't fake a high finding. If outbound DNS is blocked, the system resolver's answer stands; set FINDMYTAKEOVER_CONFIRM_RESOLVERS to resolvers the network allows.
- The console prints how long each provider took. For a slow scan, raise
FINDMYTAKEOVER_MAX_WORKERS (default 8); if collection_errors mention throttling or rate limits, lower it instead.
3. Check completeness first
If summary.complete is false (console: "WARNING: the scan is incomplete"), some DNS or inventory was not read. collection_errors names the provider, scope and API that failed — usually a missing permission (an Azure AuthorizationFailed shows up here too). A missing inventory makes live records look dangling, so report the gaps before the findings and offer to fix and rerun.
4. Report
Rank by confidence, highest first:
| confidence | Meaning | Treat as | |
|---|---|---|---|
high | SaaS target is NXDOMAIN, or serves the provider's unclaimed-site page | Likely claimable now — urgent | |
inventory-miss | Cloud-looking target not in any scanned account | Dangling, unless an unscanned account owns it | |
target-nxdomain | MX / SRV / SPF target doesn't exist | Broken mail/SPF; a takeover only if that domain is registrable (check WHOIS) | |
fingerprinted-still-resolving / -dns-unknown / -unverified | Known takeover-prone SaaS, not confirmed | Review; suggest --verify-http | |
unclassified-third-party | Points outside every known cloud/SaaS | Low; ask the user who owns it |
Present a table per tier: Record · Type · Target · Confidence · DNS provider · Account. Call out customer-named and *-prod hosts for manual confirmation.
5. Remediate (show, don't run)
The tool only reports. For each confirmed record:
- Re-check it now (
dig +short <record> <type>and, for a CNAME, the
target) — it may have been fixed or re-pointed since the scan.
- Show the deletion for the DNS provider: `aws route53
change-resource-record-sets (DELETE change batch), gcloud dns record-sets delete, az network dns record-set <type> delete, Cloudflare DELETE /zones/{zone_id}/dns_records/{id}, or oci dns record rrset delete`.
DNS deletion is outward-facing and hard to reverse — show the command and let the user run it. Only run it yourself when explicitly told to, and never batch-delete customer-named or *-prod records without confirming each one. Never delete an apex MX without asking where mail should go instead.
6. Make it recurring (if asked)
--baseline previous.jsonmarks each findingnew: true/falseand adds
new / resolved to the report; with a baseline, --fail-on-findings fails only on new findings. A missing baseline file is treated as empty.
--fail-on-incompleteexits 2 when the scan had gaps. With both flags,
failing findings take precedence (exit 1).
--alert-webhook URL(repeatable) orFINDMYTAKEOVER_ALERT_WEBHOOKS
(space-separated) posts new findings at --alert-confidence levels. Slack URLs get Slack formatting, anything else gets JSON. Keep webhook URLs in secrets — never in the config or the repo.
examples/github-actions-daily.ymlwires all of this into a daily GitHub
Actions job with OIDC cloud auth, the previous report as baseline, and one GitHub issue per finding. Copy it rather than writing a workflow from scratch.
- Into security tooling:
--json-format ocsf(SIEMs, Security Lake),
--json-format defectdojo, or --security-hub (imports into the current AWS account/region; needs securityhub:BatchImportFindings). Ids are stable, so daily re-imports update in place. From Python, call findmytakeover.scan() instead of parsing the CLI.
Before a Terraform apply
When the user is about to destroy infrastructure, or asks to stop dangling records from being created, check the plan instead of scanning:
It reports records (in the plan, plus live DNS if a config is present) that point at a resource the plan destroys. Without a config file it needs no cloud credentials, so it suits a pull-request check. The fix is to delete or re-point those records in the same change.
Environment variables
All optional; the tool runs with none set.
| Variable | Default | What it does | |
|---|---|---|---|
FINDMYTAKEOVER_MAX_WORKERS | 8 | Threads per provider pool. Raise for slow scans; lower if errors mention throttling. | |
FINDMYTAKEOVER_CONFIRM_RESOLVERS | 1.1.1.1,8.8.8.8 | Public resolvers that can overrule an NXDOMAIN (comma-separated). Empty string disables the check. | |
FINDMYTAKEOVER_ALERT_WEBHOOKS | unset (no alerts) | Webhook URLs to alert, space-separated. Added to any --alert-webhook. | |
CLOUDFLARE_API_TOKEN | unset | Cloudflare token used with credentials: default. | |
AWS_REGION | unset | Region for --security-hub imports (or the profile's region). |
Not a takeover risk
Bucket these as "stale / out of scope", not takeover risks:
- Cert validation —
*.acm-validations.aws,
*.authorize.certificatemanager.goog, _acme-challenge.*.
- Email auth (DKIM etc.) — CNAMEs into live SaaS zones (
*.domainkey.*,
*.dkim.*, *.hubspotemail.net, ...). Expected to have no inventory in the user's accounts.
- SOA / apex NS — out of scope; never delete as part of this.
- Private / internal records — records named under
.internal,.local
or cluster DNS, or pointing at private/reserved IPs, are filtered out (counted, not reported).
- Resources in an account that wasn't scanned — the #1 false positive.
Widen the scan, or add the range/domain to exclude: once the user confirms ownership.
Pitfalls
- Matching already normalises trailing dots, case, Route 53
dualstack.
aliases, IPv6 forms and S3 endpoint hostnames (to the bucket name). If a known-good record still shows up, compare its value with the dump before assuming a bug.
- NS delegations are checked only when they point at a cloud nameserver
pool (Route 53, Azure / Azure Gov, Google, Cloudflare, OCI). The child zone is proven live from the infra side, so the provider hosting it must have infra enabled.
- A permissions error is a credentials problem, not a tool bug: name the
missing permission from collection_errors and stop there.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/dangling-dns-finder/SKILL.md
Popularity
- Repository stars
- 178
- Repository forks
- 11
- 7-day trend score
- 26
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/anirudhbiyani/findmytakeover/dangling-dns-finder)