CNAME Chains That Outlive the SaaS Account Behind Them
A CNAME chain provisioned for a SaaS custom domain can keep resolving through a vendor's shared edge network long after the underlying account is deleted, because the intermediate hop stays alive and only the final hostname claim expires. Standard dangling-DNS scanners check for NXDOMAIN or dead IPs, miss this state entirely, and never flag the exposure until an attacker claims the same hostname on the same platform.
At a glance
- Unsafe setting
- A CNAME record pointing to a multi-tenant SaaS edge domain is left in place after the vendor account or project behind it is deleted.
- Failure trigger
- The vendor's edge still resolves and serves TLS for the hostname, so standard NXDOMAIN-based dangling-DNS checks report the record as healthy.
- Blast radius
- An attacker claims the same hostname on the same SaaS platform, gets a valid certificate issued, and serves content or intercepts callbacks under the trusted parent domain.
- Recommended control
- Resolve the full CNAME chain, probe with the original Host header for the vendor's unclaimed-domain signature, and delete the DNS record automatically when the corresponding SaaS resource is destroyed in Terraform.
Fix commands and configuration
dig +trace app.company.comdepends_onThe Trap
Orphaned CNAME chains pointing into a decommissioned SaaS tenant, where the DNS record itself never breaks but the hostname claim behind it silently expires.
The Default State
Provisioning a custom domain for Vercel, Shopify, Zendesk or any multi-tenant edge platform follows the same pattern: create a CNAME from app.company.com to the vendor’s alias (cname.vercel-dns.com, shops.myshopify.com, custom.zendesk.com), the vendor’s edge terminates TLS and routes by Host header rather than by IP, and the record goes into Terraform or the DNS console as a one-off entry. When the project is deleted, the trial lapses, or the team migrates platforms, the decommission runbook removes the compute, the billing account and sometimes the vendor-side domain mapping — but the Route 53 or Azure DNS CNAME record is rarely tracked as a dependent resource, so it survives untouched.
The Blast Radius
Because the vendor’s edge domain itself stays live and answers on port 443 for every hostname, the CNAME chain never resolves to NXDOMAIN and never times out — it just returns a generic “domain not configured” page for the unclaimed host. Any dangling-DNS scanner that only checks for broken resolution or dead IPs marks the record healthy. An attacker registers a new account on the same platform, adds the exact orphaned hostname as their custom domain, passes whatever verification the vendor requires (often nothing more than the CNAME already pointing at their edge), and the platform’s automatic Let’s Encrypt HTTP-01 issuance mints a valid certificate for company.com’s subdomain under the attacker’s control. From there they serve arbitrary content under a trusted origin, harvest cookies set with Domain=.company.com, receive misdirected SAML ACS POSTs or OAuth redirect callbacks still configured against that subdomain, and pass CSP and SPF checks that trust the parent zone.
The Lead Mechanic Fix
Stop treating vendor CNAME targets as inert strings. Resolve the full chain with dig +trace app.company.com, take the terminal IP, then send an HTTP probe with the original Host header set and match the response body against the vendor’s known “unclaimed” signature (Vercel returns DEPLOYMENT_NOT_FOUND, Shopify returns a themed 404, Zendesk returns a specific help-centre error) rather than trusting a 200 or 404 status code alone. Wire DNS record lifecycle into the same Terraform module that creates the SaaS resource — a destroy-time provisioner or explicit depends_on between the vercel_project/shopify_shop resource and the aws_route53_record — so the CNAME is deleted the moment the vendor resource is destroyed, not left as an unmanaged orphan. Run a scheduled subdomain-takeover sweep against every third-party CNAME in the zone using an up-to-date fingerprint list, and tag every SaaS CNAME with a TXT record carrying an owner and review date, purged automatically after 90 days of inactivity confirmed against the vendor’s domains API.