The DNS Record Nobody Remembered to Delete
Six months ago, someone spun up promo.yourapp.com on GitHub Pages for a campaign landing page. The campaign ended, the GitHub repo got deleted during a cleanup sprint, and everyone moved on.…
Six months ago, someone spun up promo.yourapp.com on GitHub Pages for a campaign landing page. The campaign ended, the GitHub repo got deleted during a cleanup sprint, and everyone moved on. Nobody removed the DNS record that still points promo.yourapp.com at that now-deleted GitHub Pages site.
That leftover DNS record is called a dangling CNAME, and it's not just untidy. If the abandoned GitHub Pages resource can be claimed by another GitHub user, an attacker may be able to configure that resource to serve content through promo.yourapp.com, your real domain, in the browser's address bar, with your padlock. This is a subdomain takeover, and it's one of the more underestimated vulnerability classes precisely because it doesn't require breaking anything. It just requires someone forgetting to clean up.
What a Subdomain Takeover Actually Is
Most subdomains are set up with a CNAME record, a DNS entry that says "this subdomain is really just an alias for that other address." promo.yourapp.com might have a CNAME pointing to yourapp.github.io, or status.yourapp.com pointing to a Heroku app, or docs.yourapp.com pointing to a Netlify deployment.
As long as the service on the other end of that CNAME is still active and still owned by you, this is completely normal and fine. The problem starts when that service gets deleted, decommissioned, or migrated away from, and nobody removes the DNS record pointing at it. The CNAME is still there, still resolving, still telling browsers "this is a real part of yourapp.com," but the thing it points to no longer belongs to anyone. On platforms that let you claim a resource by name, GitHub Pages, Heroku, many CDN and static-hosting providers, someone else can claim the abandoned resource, while the existing DNS record continues directing requests for your subdomain to it.
Why This Is More Dangerous Than It Sounds
The attacker doesn't need to compromise your servers, guess a password, or exploit a bug in your code. They need to notice a dangling DNS record and register a free account on whatever service it points to. From there:
- Phishing becomes far more convincing. A login page served from account.yourapp.com is inherently more trustworthy than one from a lookalike domain, because it is your domain. An attacker may also be able to obtain a valid TLS certificate for the subdomain, depending on the hosting provider and certificate-validation setup.
- It can affect cookie and origin-based trust. Depending on how cookies, CORS, CSP, OAuth redirects, and other trust relationships are configured, a compromised subdomain can create security risks that an unrelated external domain could not.
- It sits there quietly until someone finds it. There's no error, no downtime, no alert. The DNS record can remain in place without causing an obvious outage, so unless someone checks the subdomain or monitors the underlying resource, nobody may notice the exposure.
Why QA Should Be the Team That Catches This
This isn't necessarily an application bug, and a functional test suite may never encounter it. But the failure mode is familiar to QA: a change was made, a dependency was removed, and the cleanup was never verified.
That's the same category of risk as a feature flag left on after a feature was supposed to be fully rolled back, or a database migration that didn't actually drop the old column. When infrastructure changes, QA doesn't need to become responsible for DNS administration. Its role can be to make sure security-sensitive cleanup is included in the verification process, and that the relevant checks are actually completed before the change is considered done.
How to Actually Check for This
Manually, for a quick check: Search your domain on crt.sh, a free public Certificate Transparency log search. Certificate Transparency logs can reveal subdomains for which certificates have been issued, making them a useful source for discovering forgotten or previously used subdomains. Cross-reference that list against what you'd expect to still be active.
For each subdomain you find, check what it actually points to:
dig CNAME promo.yourapp.comIf the CNAME resolves to a service (a .github.io, .herokuapp.com, .netlify.app address, or similar) and visiting the subdomain shows an error like "There isn't a GitHub Pages site here" or "No such app," that's a strong signal worth investigating further. A dangling CNAME alone doesn't prove a takeover is possible, the target must also correspond to a resource that can actually be claimed or controlled by someone else, so treat this as a lead to confirm, not a finding to report as-is.
At scale, this needs tooling, not a manual list. Passive subdomain enumeration tools such as subfinder can help discover subdomains from public sources like Certificate Transparency logs, DNS aggregators, and public archives, without sending any traffic to your servers. A separate takeover-detection step can then resolve those subdomains, inspect their CNAME targets and HTTP responses, and compare them against known service fingerprints. This is exactly the kind of check that belongs in a recurring automated scan rather than a quarterly manual audit, since a new dangling record can appear the moment any team decommissions any service, not on a schedule anyone remembers to check against.
Building This Into a Decommissioning Checklist
The actual fix is mostly process, not tooling. Any time a service, environment, or subdomain is shut down:
- Remove or update the DNS record before decommissioning the external resource. If the subdomain still needs to serve users temporarily, point it to a resource you control rather than leaving it attached to a resource you're about to delete.
- Search your Certificate Transparency history periodically, not just at decommission time, since old records can be missed the first time around.
- Treat "delete this service" tickets the same way you'd treat a regression risk. Add a verification step: confirm the DNS record is gone, not just that the service is.
- Run a takeover check as part of your regular scan cadence, alongside whatever else you're already checking after infrastructure changes.
None of this requires new expertise. It requires adding one more item to the list of things that get verified after something is torn down, which is a list QA already owns for almost everything else.
Where Automated Security Scanning Fits
Manual checks work well when you have a small, well-documented set of subdomains. They get harder to maintain as infrastructure changes, new environments spin up, old ones get abandoned, and nobody's tracking the full list in one place.
This is exactly the kind of check FlawPilot's scanner is built to run continuously: verifying that the URL you point it at, and the infrastructure behind it, still resolves to something you actually control, before an attacker finds it first. That gives QA and infrastructure teams another verification layer after deployments, migrations, and service decommissions, without anyone needing to remember to run a manual check on a schedule.
The goal isn't to replace a penetration test. It's to catch common exposure patterns continuously, before they become forgotten infrastructure nobody knows to look for.
Frequently asked questions
Final Thoughts
A subdomain takeover doesn't require an attacker to find a bug in your code. It requires your team to forget one DNS record after deleting one service, which is an easy thing to forget precisely because nothing breaks when it happens.
That's exactly why it belongs on a checklist instead of relying on memory. Whether it's a manual crt.sh search after every decommission or a recurring automated scan, the fix is the same discipline QA already applies everywhere else: don't assume cleanup happened, verify it did.
How FlawPilot helps
FlawPilot helps you find security and quality issues in your AI-built app and gives you a clear path to fix them. Instead of simply telling you that something is wrong, FlawPilot explains what the issue means, why it matters, and what you should do next.
FlawPilot checks your deployed website across security, performance, infrastructure, and SEO, while its source-code security scanner checks your code for vulnerabilities, insecure patterns, hardcoded secrets, and vulnerable dependencies. Every finding is prioritized and explained in plain English, so you can understand the problem even without a security background.
Each issue includes practical remediation guidance, such as the configuration change, DNS record, security header, or code change needed to fix it. For supported findings, FlawPilot can also provide AI-powered remediation guidance with step-by-step instructions and suggested code fixes, helping you move from discovering a vulnerability to actually resolving it.
Connect your Git provider to run a source code security scan alongside your live website scan. FlawPilot brings application security findings, code vulnerabilities, secrets, and dependency issues into one place instead of requiring separate tools for your deployed app and repository.
FlawPilot also fits into your existing development workflow. Use the REST API to access scores and findings programmatically, add an embeddable security badge to your website or README, or connect through the MCP server so AI coding tools such as Claude, Cursor, or ChatGPT can access your findings and help you work through remediation.
For deeper issues that require engineering work, FlawPilot can provide a prioritized remediation roadmap and help your engineering team address the findings directly, including security configuration, DNS, application code, and other fixes.
The boundaries are clear. The public website scan checks only publicly accessible signals, with no agent, credentials, or software installation required. Source-code scanning is opt-in and read-only: you connect your Git provider and FlawPilot analyzes the repository to identify security issues. Fixes are not automatically applied or merged without human review.
FlawPilot brings detection, explanation, remediation, and verification together, helping you confidently check and secure your AI-built application before it reaches real users.
Verify your AI-generated app is production-ready.
80+ security checks in 60 seconds - free, no account needed.
No account needed · Public signals only · Results in minutes