diff --git a/config.json b/config.json index e88dec7..2d3691b 100644 --- a/config.json +++ b/config.json @@ -1,314 +1,464 @@ { - "config": { - "output_dir": "output", - "max_threads": 2, - "timeout": 1, - "nameservers": "1.1.1.1,8.8.8.8", - "verbose": false, - "retries": 2, - "evidence": true, - "extreme": false - }, - "domain_categorisation": { - "acquia": { - "regex": "\\.acquia\\.com\\.", - "recommendation": "Delete the CNAME record — the Acquia site no longer exists", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" - }, - "akamai": { - "regex": "\\.akamai\\.net\\.|\\.akamaihd\\.net\\.", - "recommendation": "Remove the CNAME record if the Akamai property is no longer active", - "evidence": "https://www.akamai.com/us/en/resources/faq.jsp" - }, - "algolia": { - "regex": "\\.algolia\\.net\\.|\\.algolianet\\.com\\.", - "recommendation": "Remove the CNAME if the Algolia index no longer exists", - "evidence": "https://www.algolia.com/doc/" - }, - "amazon_ses": { - "regex": "\\.dkim\\.amazonses\\.com\\.", - "recommendation": "Remove the DKIM CNAME if SES sending is no longer configured", - "evidence": "https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-authentication-dkim.html" - }, - "api_gateway": { - "regex": "\\.execute-api\\.amazonaws\\.com\\.", - "recommendation": "Delete the CNAME — the API Gateway stage has been removed", - "evidence": "https://docs.aws.amazon.com/apigateway/latest/developerguide/" - }, - "aws_acm": { - "regex": "\\.acm-validations\\.aws\\.", - "recommendation": "Do not remove — this record validates an ACM certificate", - "evidence": "https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html" - }, - "aws_amplify": { - "regex": "\\.amplifyapp\\.com\\.", - "recommendation": "Delete the CNAME — the Amplify app or branch no longer exists", - "evidence": "https://docs.amplify.aws" - }, - "aws_elastic_beanstalk": { - "regex": "\\.elasticbeanstalk\\.com\\.", - "recommendation": "Delete the CNAME — the Elastic Beanstalk environment has been terminated; the subdomain may be reclaimable", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/97" - }, - "aws_elb": { - "regex": "\\.elb\\.amazonaws\\.com\\.", - "recommendation": "Delete the CNAME — the AWS Elastic Load Balancer no longer exists; ELB names are region-scoped and can be claimed by any AWS account in the same region", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/137" - }, - "aws_s3": { - "regex": "\\.s3\\.amazonaws\\.com\\.|\\.s3-website[.-][a-z0-9-]+\\.amazonaws\\.com\\.|\\.s3\\.dualstack\\.[a-z0-9-]+\\.amazonaws\\.com\\.", - "recommendation": "Delete the CNAME or recreate the S3 bucket — unclaimed buckets can be registered by anyone in the same region", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/36" - }, - "azure": { - "regex": "\\.azurewebsites\\.net\\.|\\.blob\\.core\\.windows\\.net\\.|\\.table\\.core\\.windows\\.net\\.|\\.queue\\.core\\.windows\\.net\\.|\\.database\\.windows\\.net\\.|\\.azureedge\\.net\\.|\\.azure-api\\.net\\.|\\.microsoftonline\\.com\\.|\\.trafficmanager\\.net\\.", - "recommendation": "Delete the CNAME — the Azure resource has been removed; dangling Azure records are exploitable", - "evidence": "https://docs.microsoft.com/en-us/azure/security/fundamentals/subdomain-takeover" - }, - "bitbucket": { - "regex": "\\.bitbucket\\.io\\.|\\.bitbucket\\.org\\.", - "recommendation": "Delete the CNAME — the Bitbucket Pages site no longer exists", - "evidence": "https://support.atlassian.com/bitbucket-cloud/docs/" - }, - "box": { - "regex": "\\.box\\.com\\.", - "recommendation": "Remove the CNAME if the Box embed is no longer active", - "evidence": "https://support.box.com" - }, - "cloud_functions": { - "regex": "\\.cloudfunctions\\.net\\.", - "recommendation": "Delete the CNAME — the Cloud Function no longer exists", - "evidence": "https://cloud.google.com/functions/docs" - }, - "cloudflare": { - "regex": "\\.cloudflare\\.com\\.|\\.cf\\.cloudflare\\.com\\.|\\.cloudflare-dns\\.com\\.", - "recommendation": "Remove the CNAME — the Cloudflare zone or page rule is no longer configured", - "evidence": "https://developers.cloudflare.com" - }, - "cloudflare_ips": { - "regex": "\\.cf\\.cloudflareresolve\\.com\\.|\\.cloudflareresolve\\.com\\.", - "recommendation": "Remove the CNAME if the Cloudflare routing is no longer active", - "evidence": "https://developers.cloudflare.com" - }, - "cloudfront": { - "regex": "\\.cloudfront\\.net\\.", - "recommendation": "Delete the CNAME — the CloudFront distribution has been removed", - "evidence": "https://aws.amazon.com/premiumsupport/knowledge-center/delete-cloudfront-cname-entry/" - }, - "datadog": { - "regex": "\\.datadoghq\\.com\\.", - "recommendation": "Remove the CNAME if the Datadog custom domain is no longer mapped", - "evidence": "https://docs.datadoghq.com" - }, - "digitalocean": { - "regex": "\\.digitaloceanspaces\\.com\\.|\\.do\\.digitaloceanspaces\\.com\\.", - "recommendation": "Delete the CNAME or recreate the Space — unclaimed Spaces are reclaimable", - "evidence": "https://www.digitalocean.com/docs/spaces/" - }, - "docusign": { - "regex": "\\.docusign\\.net\\.", - "recommendation": "Remove the CNAME if DocuSign sending is no longer configured", - "evidence": "https://support.docusign.com" - }, - "dropbox": { - "regex": "\\.dropboxusercontent\\.com\\.|\\.dropbox\\.com\\.", - "recommendation": "Remove the CNAME if the Dropbox share is no longer active", - "evidence": "https://help.dropbox.com" - }, - "dyn": { - "regex": "\\.dynect\\.net\\.|\\.dyn\\.com\\.", - "recommendation": "Delete the CNAME — the Dyn DNS entry no longer resolves", - "evidence": "https://help.dyn.com" - }, - "fastly": { - "regex": "\\.fastly\\.net\\.|\\.fastlylb\\.net\\.", - "recommendation": "Delete the CNAME — the Fastly service is no longer configured", - "evidence": "https://docs.fastly.com" - }, - "firebase": { - "regex": "\\.firebaseio\\.com\\.|\\.firebasedatabase\\.app\\.", - "recommendation": "Delete the CNAME — the Firebase project or database no longer exists", - "evidence": "https://firebase.google.com/docs" - }, - "fly_io": { - "regex": "\\.fly\\.dev\\.|\\.flycast\\.dev\\.", - "recommendation": "Delete the CNAME — the Fly.io app has been deleted; the name may be reclaimable", - "evidence": "https://fly.io/docs/networking/custom-domain/" - }, - "ghost": { - "regex": "\\.ghost\\.io\\.", - "recommendation": "Delete the CNAME — the Ghost(Pro) blog no longer exists; the subdomain is reclaimable", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/41" - }, - "github": { - "regex": "\\.github\\.io\\.|\\.githubusercontent\\.com\\.", - "recommendation": "Delete the CNAME or recreate the GitHub Pages site — the username/org or repo no longer exists", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/37" - }, - "google": { - "regex": "\\.googlehosted\\.com\\.|\\.googledomains\\.com\\.|\\.googleapis\\.com\\.|\\.googleusercontent\\.com\\.|\\.gstatic\\.com\\.|\\.google\\.", - "recommendation": "Remove the CNAME if the Google-hosted resource no longer exists", - "evidence": "https://developers.google.com" - }, - "heroku": { - "regex": "\\.herokudns\\.com\\.|\\.herokuapp\\.com\\.|\\.herokussl\\.com\\.", - "recommendation": "Delete the CNAME — the Heroku app no longer exists; the subdomain can be claimed by anyone", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/2" - }, - "hubspot": { - "regex": "\\.hubspot\\.net\\.|\\.hs-sites\\.com\\.|\\.hubspotpagebuilder\\.com\\.", - "recommendation": "Delete the CNAME — the HubSpot portal or landing page no longer exists", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/22" - }, - "incapsula": { - "regex": "\\.incapdns\\.net\\.|\\.impervadns\\.net\\.", - "recommendation": "Remove the CNAME if the Imperva/Incapsula site is no longer protected", - "evidence": "https://docs.imperva.com/bundle/cloud-application-security/page/more/faq/incapsula-nameserver.html" - }, - "jira": { - "regex": "\\.jira\\.com\\.|\\.atlassian\\.net\\.", - "recommendation": "Remove the CNAME if the Atlassian product custom domain is no longer mapped", - "evidence": "https://support.atlassian.com/jira-cloud/" - }, - "launchrock": { - "regex": "\\.launchrock\\.com\\.", - "recommendation": "Delete the CNAME — the Launchrock page no longer exists", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" - }, - "microsoft": { - "regex": "\\.onmicrosoft\\.com\\.", - "recommendation": "Remove the CNAME if the Microsoft 365 tenant is no longer active", - "evidence": "https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/customize-tenant-name" - }, - "netlify": { - "regex": "\\.netlify\\.com\\.|\\.netlify\\.app\\.|\\.netlifyglobalcdn\\.com\\.", - "recommendation": "Delete the CNAME — the Netlify site no longer exists; the subdomain may be reclaimable", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/40" - }, - "newrelic": { - "regex": "\\.newrelic\\.com\\.", - "recommendation": "Remove the CNAME if the New Relic custom domain is no longer mapped", - "evidence": "https://docs.newrelic.com" - }, - "ngrok": { - "regex": "\\.ngrok\\.io\\.|\\.ngrok-free\\.app\\.", - "recommendation": "Delete the CNAME — the ngrok tunnel is no longer active", - "evidence": "https://ngrok.com/docs" - }, - "oracle": { - "regex": "\\.oraclecloud\\.com\\.|\\.oracle\\.com\\.", - "recommendation": "Remove the CNAME if the Oracle Cloud resource no longer exists", - "evidence": "https://docs.oracle.com/en/cloud/" - }, - "pantheon": { - "regex": "\\.pantheonsite\\.io\\.|\\.pantheon\\.io\\.", - "recommendation": "Delete the CNAME — the Pantheon environment no longer exists", - "evidence": "https://pantheon.io/docs" - }, - "railway": { - "regex": "\\.railway\\.app\\.", - "recommendation": "Delete the CNAME — the Railway service has been deleted; the subdomain may be reclaimable", - "evidence": "https://docs.railway.app/deploy/custom-domains" - }, - "readthedocs": { - "regex": "\\.readthedocs\\.io\\.|\\.readthedocs-hosted\\.com\\.", - "recommendation": "Delete the CNAME or reclaim the ReadTheDocs project — the documentation project name is reclaimable", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/9" - }, - "render": { - "regex": "\\.onrender\\.com\\.", - "recommendation": "Delete the CNAME — the Render service has been suspended or deleted", - "evidence": "https://render.com/docs/custom-domains" - }, - "salesforce": { - "regex": "\\.custdkim\\.salesforce\\.com\\.", - "recommendation": "Remove the DKIM CNAME if Salesforce sending is no longer configured", - "evidence": "https://help.salesforce.com/articleView?id=000313497&type=1&mode=1" - }, - "sendgrid": { - "regex": "\\.sendgrid\\.net\\.", - "recommendation": "Remove the CNAME if SendGrid domain authentication is no longer active", - "evidence": "https://sendgrid.com/docs/ui/account-and-settings/how-to-set-up-domain-authentication/" - }, - "shopify": { - "regex": "\\.myshopify\\.com\\.|\\.shopify\\.com\\.", - "recommendation": "Delete the CNAME — the Shopify store is no longer active", - "evidence": "https://help.shopify.com" - }, - "slack": { - "regex": "\\.slack\\.com\\.", - "recommendation": "Remove the CNAME if the Slack workspace custom domain is no longer mapped", - "evidence": "https://slack.com/help" - }, - "squarespace": { - "regex": "\\.squarespace\\.com\\.", - "recommendation": "Delete the CNAME — the Squarespace site no longer exists", - "evidence": "https://support.squarespace.com" - }, - "statuspage": { - "regex": "\\.statuspage\\.io\\.", - "recommendation": "Delete the CNAME — the Statuspage page no longer exists; the subdomain may be reclaimable", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/11" - }, - "strapi": { - "regex": "\\.strapi\\.io\\.", - "recommendation": "Delete the CNAME — the Strapi Cloud project no longer exists", - "evidence": "https://strapi.io/documentation" - }, - "strikingly": { - "regex": "\\.strikingly\\.com\\.", - "recommendation": "Delete the CNAME — the Strikingly site no longer exists", - "evidence": "https://support.strikingly.com" - }, - "surge": { - "regex": "\\.surge\\.sh\\.", - "recommendation": "Delete the CNAME or republish to the same subdomain — unclaimed Surge projects are immediately reclaimable", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/1" - }, - "trello": { - "regex": "\\.trello\\.com\\.", - "recommendation": "Remove the CNAME if the Trello board custom domain is no longer mapped", - "evidence": "https://help.trello.com" - }, - "tumblr": { - "regex": "\\.tumblr\\.com\\.", - "recommendation": "Delete the CNAME — the Tumblr blog no longer exists; the custom domain can be reclaimed", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/12" - }, - "unbounce": { - "regex": "\\.unbouncepages\\.com\\.", - "recommendation": "Delete the CNAME — the Unbounce landing page no longer exists", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/26" - }, - "vercel": { - "regex": "\\.vercel\\.app\\.|\\.now\\.sh\\.", - "recommendation": "Delete the CNAME — the Vercel project or deployment no longer exists", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/93" - }, - "weebly": { - "regex": "\\.weebly\\.com\\.", - "recommendation": "Delete the CNAME — the Weebly site no longer exists", - "evidence": "https://www.weebly.com/app/help/us/en" - }, - "wix": { - "regex": "\\.wix\\.com\\.|\\.editorx\\.com\\.|\\.wixsite\\.com\\.", - "recommendation": "Delete the CNAME — the Wix site no longer exists", - "evidence": "https://support.wix.com" - }, - "wordpress": { - "regex": "\\.wordpress\\.com\\.|\\.wp\\.com\\.", - "recommendation": "Delete the CNAME — the WordPress.com site no longer exists", - "evidence": "https://wordpress.org/support/" - }, - "zendesk": { - "regex": "\\.zendesk\\.com\\.", - "recommendation": "Delete the CNAME — the Zendesk Help Centre custom domain is no longer mapped", - "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/23" - }, - "zoom": { - "regex": "\\.zoom\\.us\\.", - "recommendation": "Remove the CNAME if the Zoom vanity URL is no longer active", - "evidence": "https://support.zoom.us" - } + "config": { + "output_dir": "output", + "max_threads": 2, + "timeout": 1, + "nameservers": "1.1.1.1,8.8.8.8", + "verbose": false, + "retries": 2, + "evidence": true, + "extreme": false + }, + "domain_categorisation": { + "acquia": { + "regex": "\\.acquia\\.com\\.", + "recommendation": "Delete the CNAME record \u2014 the Acquia site no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "akamai": { + "regex": "\\.akamai\\.net\\.|\\.akamaihd\\.net\\.", + "recommendation": "Remove the CNAME record if the Akamai property is no longer active", + "evidence": "https://www.akamai.com/us/en/resources/faq.jsp" + }, + "algolia": { + "regex": "\\.algolia\\.net\\.|\\.algolianet\\.com\\.", + "recommendation": "Remove the CNAME if the Algolia index no longer exists", + "evidence": "https://www.algolia.com/doc/" + }, + "amazon_ses": { + "regex": "\\.dkim\\.amazonses\\.com\\.", + "recommendation": "Remove the DKIM CNAME if SES sending is no longer configured", + "evidence": "https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-authentication-dkim.html" + }, + "api_gateway": { + "regex": "\\.execute-api\\.amazonaws\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the API Gateway stage has been removed", + "evidence": "https://docs.aws.amazon.com/apigateway/latest/developerguide/" + }, + "aws_acm": { + "regex": "\\.acm-validations\\.aws\\.", + "recommendation": "Do not remove \u2014 this record validates an ACM certificate", + "evidence": "https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html" + }, + "aws_amplify": { + "regex": "\\.amplifyapp\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Amplify app or branch no longer exists", + "evidence": "https://docs.amplify.aws" + }, + "aws_elastic_beanstalk": { + "regex": "\\.elasticbeanstalk\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Elastic Beanstalk environment has been terminated; the subdomain may be reclaimable", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/97" + }, + "aws_elb": { + "regex": "\\.elb\\.amazonaws\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the AWS Elastic Load Balancer no longer exists; ELB names are region-scoped and can be claimed by any AWS account in the same region", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/137" + }, + "aws_s3": { + "regex": "\\.s3\\.amazonaws\\.com\\.|\\.s3-website[.-][a-z0-9-]+\\.amazonaws\\.com\\.|\\.s3\\.dualstack\\.[a-z0-9-]+\\.amazonaws\\.com\\.", + "recommendation": "Delete the CNAME or recreate the S3 bucket \u2014 unclaimed buckets can be registered by anyone in the same region", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/36" + }, + "azure": { + "regex": "\\.azurewebsites\\.net\\.|\\.blob\\.core\\.windows\\.net\\.|\\.table\\.core\\.windows\\.net\\.|\\.queue\\.core\\.windows\\.net\\.|\\.database\\.windows\\.net\\.|\\.azureedge\\.net\\.|\\.azure-api\\.net\\.|\\.microsoftonline\\.com\\.|\\.trafficmanager\\.net\\.", + "recommendation": "Delete the CNAME \u2014 the Azure resource has been removed; dangling Azure records are exploitable", + "evidence": "https://docs.microsoft.com/en-us/azure/security/fundamentals/subdomain-takeover" + }, + "bitbucket": { + "regex": "\\.bitbucket\\.io\\.|\\.bitbucket\\.org\\.", + "recommendation": "Delete the CNAME \u2014 the Bitbucket Pages site no longer exists", + "evidence": "https://support.atlassian.com/bitbucket-cloud/docs/" + }, + "box": { + "regex": "\\.box\\.com\\.", + "recommendation": "Remove the CNAME if the Box embed is no longer active", + "evidence": "https://support.box.com" + }, + "cloud_functions": { + "regex": "\\.cloudfunctions\\.net\\.", + "recommendation": "Delete the CNAME \u2014 the Cloud Function no longer exists", + "evidence": "https://cloud.google.com/functions/docs" + }, + "cloudflare": { + "regex": "\\.cloudflare\\.com\\.|\\.cf\\.cloudflare\\.com\\.|\\.cloudflare-dns\\.com\\.", + "recommendation": "Remove the CNAME \u2014 the Cloudflare zone or page rule is no longer configured", + "evidence": "https://developers.cloudflare.com" + }, + "cloudflare_ips": { + "regex": "\\.cf\\.cloudflareresolve\\.com\\.|\\.cloudflareresolve\\.com\\.", + "recommendation": "Remove the CNAME if the Cloudflare routing is no longer active", + "evidence": "https://developers.cloudflare.com" + }, + "cloudfront": { + "regex": "\\.cloudfront\\.net\\.", + "recommendation": "Delete the CNAME \u2014 the CloudFront distribution has been removed", + "evidence": "https://aws.amazon.com/premiumsupport/knowledge-center/delete-cloudfront-cname-entry/" + }, + "datadog": { + "regex": "\\.datadoghq\\.com\\.", + "recommendation": "Remove the CNAME if the Datadog custom domain is no longer mapped", + "evidence": "https://docs.datadoghq.com" + }, + "digitalocean": { + "regex": "\\.digitaloceanspaces\\.com\\.|\\.do\\.digitaloceanspaces\\.com\\.", + "recommendation": "Delete the CNAME or recreate the Space \u2014 unclaimed Spaces are reclaimable", + "evidence": "https://www.digitalocean.com/docs/spaces/" + }, + "docusign": { + "regex": "\\.docusign\\.net\\.", + "recommendation": "Remove the CNAME if DocuSign sending is no longer configured", + "evidence": "https://support.docusign.com" + }, + "dropbox": { + "regex": "\\.dropboxusercontent\\.com\\.|\\.dropbox\\.com\\.", + "recommendation": "Remove the CNAME if the Dropbox share is no longer active", + "evidence": "https://help.dropbox.com" + }, + "dyn": { + "regex": "\\.dynect\\.net\\.|\\.dyn\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Dyn DNS entry no longer resolves", + "evidence": "https://help.dyn.com" + }, + "fastly": { + "regex": "\\.fastly\\.net\\.|\\.fastlylb\\.net\\.", + "recommendation": "Delete the CNAME \u2014 the Fastly service is no longer configured", + "evidence": "https://docs.fastly.com" + }, + "firebase": { + "regex": "\\.firebaseio\\.com\\.|\\.firebasedatabase\\.app\\.", + "recommendation": "Delete the CNAME \u2014 the Firebase project or database no longer exists", + "evidence": "https://firebase.google.com/docs" + }, + "fly_io": { + "regex": "\\.fly\\.dev\\.|\\.flycast\\.dev\\.", + "recommendation": "Delete the CNAME \u2014 the Fly.io app has been deleted; the name may be reclaimable", + "evidence": "https://fly.io/docs/networking/custom-domain/" + }, + "ghost": { + "regex": "\\.ghost\\.io\\.", + "recommendation": "Delete the CNAME \u2014 the Ghost(Pro) blog no longer exists; the subdomain is reclaimable", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/41" + }, + "github": { + "regex": "\\.github\\.io\\.|\\.githubusercontent\\.com\\.", + "recommendation": "Delete the CNAME or recreate the GitHub Pages site \u2014 the username/org or repo no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/37" + }, + "google": { + "regex": "\\.googlehosted\\.com\\.|\\.googledomains\\.com\\.|\\.googleapis\\.com\\.|\\.googleusercontent\\.com\\.|\\.gstatic\\.com\\.|\\.google\\.", + "recommendation": "Remove the CNAME if the Google-hosted resource no longer exists", + "evidence": "https://developers.google.com" + }, + "heroku": { + "regex": "\\.herokudns\\.com\\.|\\.herokuapp\\.com\\.|\\.herokussl\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Heroku app no longer exists; the subdomain can be claimed by anyone", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/2" + }, + "hubspot": { + "regex": "\\.hubspot\\.net\\.|\\.hs-sites\\.com\\.|\\.hubspotpagebuilder\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the HubSpot portal or landing page no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/22" + }, + "incapsula": { + "regex": "\\.incapdns\\.net\\.|\\.impervadns\\.net\\.", + "recommendation": "Remove the CNAME if the Imperva/Incapsula site is no longer protected", + "evidence": "https://docs.imperva.com/bundle/cloud-application-security/page/more/faq/incapsula-nameserver.html" + }, + "jira": { + "regex": "\\.jira\\.com\\.|\\.atlassian\\.net\\.", + "recommendation": "Remove the CNAME if the Atlassian product custom domain is no longer mapped", + "evidence": "https://support.atlassian.com/jira-cloud/" + }, + "launchrock": { + "regex": "\\.launchrock\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Launchrock page no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "microsoft": { + "regex": "\\.onmicrosoft\\.com\\.", + "recommendation": "Remove the CNAME if the Microsoft 365 tenant is no longer active", + "evidence": "https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/customize-tenant-name" + }, + "netlify": { + "regex": "\\.netlify\\.com\\.|\\.netlify\\.app\\.|\\.netlifyglobalcdn\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Netlify site no longer exists; the subdomain may be reclaimable", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/40" + }, + "newrelic": { + "regex": "\\.newrelic\\.com\\.", + "recommendation": "Remove the CNAME if the New Relic custom domain is no longer mapped", + "evidence": "https://docs.newrelic.com" + }, + "ngrok": { + "regex": "\\.ngrok\\.io\\.|\\.ngrok-free\\.app\\.", + "recommendation": "Delete the CNAME \u2014 the ngrok tunnel is no longer active", + "evidence": "https://ngrok.com/docs" + }, + "oracle": { + "regex": "\\.oraclecloud\\.com\\.|\\.oracle\\.com\\.", + "recommendation": "Remove the CNAME if the Oracle Cloud resource no longer exists", + "evidence": "https://docs.oracle.com/en/cloud/" + }, + "pantheon": { + "regex": "\\.pantheonsite\\.io\\.|\\.pantheon\\.io\\.", + "recommendation": "Delete the CNAME \u2014 the Pantheon environment no longer exists", + "evidence": "https://pantheon.io/docs" + }, + "railway": { + "regex": "\\.railway\\.app\\.", + "recommendation": "Delete the CNAME \u2014 the Railway service has been deleted; the subdomain may be reclaimable", + "evidence": "https://docs.railway.app/deploy/custom-domains" + }, + "readthedocs": { + "regex": "\\.readthedocs\\.io\\.|\\.readthedocs-hosted\\.com\\.", + "recommendation": "Delete the CNAME or reclaim the ReadTheDocs project \u2014 the documentation project name is reclaimable", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/9" + }, + "render": { + "regex": "\\.onrender\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Render service has been suspended or deleted", + "evidence": "https://render.com/docs/custom-domains" + }, + "salesforce": { + "regex": "\\.custdkim\\.salesforce\\.com\\.", + "recommendation": "Remove the DKIM CNAME if Salesforce sending is no longer configured", + "evidence": "https://help.salesforce.com/articleView?id=000313497&type=1&mode=1" + }, + "sendgrid": { + "regex": "\\.sendgrid\\.net\\.", + "recommendation": "Remove the CNAME if SendGrid domain authentication is no longer active", + "evidence": "https://sendgrid.com/docs/ui/account-and-settings/how-to-set-up-domain-authentication/" + }, + "shopify": { + "regex": "\\.myshopify\\.com\\.|\\.shopify\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Shopify store is no longer active", + "evidence": "https://help.shopify.com" + }, + "slack": { + "regex": "\\.slack\\.com\\.", + "recommendation": "Remove the CNAME if the Slack workspace custom domain is no longer mapped", + "evidence": "https://slack.com/help" + }, + "squarespace": { + "regex": "\\.squarespace\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Squarespace site no longer exists", + "evidence": "https://support.squarespace.com" + }, + "statuspage": { + "regex": "\\.statuspage\\.io\\.", + "recommendation": "Delete the CNAME \u2014 the Statuspage page no longer exists; the subdomain may be reclaimable", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/11" + }, + "strapi": { + "regex": "\\.strapi\\.io\\.", + "recommendation": "Delete the CNAME \u2014 the Strapi Cloud project no longer exists", + "evidence": "https://strapi.io/documentation" + }, + "strikingly": { + "regex": "\\.strikingly\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Strikingly site no longer exists", + "evidence": "https://support.strikingly.com" + }, + "surge": { + "regex": "\\.surge\\.sh\\.", + "recommendation": "Delete the CNAME or republish to the same subdomain \u2014 unclaimed Surge projects are immediately reclaimable", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/1" + }, + "trello": { + "regex": "\\.trello\\.com\\.", + "recommendation": "Remove the CNAME if the Trello board custom domain is no longer mapped", + "evidence": "https://help.trello.com" + }, + "tumblr": { + "regex": "\\.tumblr\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Tumblr blog no longer exists; the custom domain can be reclaimed", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/12" + }, + "unbounce": { + "regex": "\\.unbouncepages\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Unbounce landing page no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/26" + }, + "vercel": { + "regex": "\\.vercel\\.app\\.|\\.now\\.sh\\.", + "recommendation": "Delete the CNAME \u2014 the Vercel project or deployment no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/93" + }, + "weebly": { + "regex": "\\.weebly\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Weebly site no longer exists", + "evidence": "https://www.weebly.com/app/help/us/en" + }, + "wix": { + "regex": "\\.wix\\.com\\.|\\.editorx\\.com\\.|\\.wixsite\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Wix site no longer exists", + "evidence": "https://support.wix.com" + }, + "wordpress": { + "regex": "\\.wordpress\\.com\\.|\\.wp\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the WordPress.com site no longer exists", + "evidence": "https://wordpress.org/support/" + }, + "zendesk": { + "regex": "\\.zendesk\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Zendesk Help Centre custom domain is no longer mapped", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz/issues/23" + }, + "zoom": { + "regex": "\\.zoom\\.us\\.", + "recommendation": "Remove the CNAME if the Zoom vanity URL is no longer active", + "evidence": "https://support.zoom.us" + }, + "webflow": { + "regex": "\\.proxy-ssl\\.webflow\\.com\\.|\\.webflow\\.io\\.", + "recommendation": "Delete the CNAME or re-add the domain in Webflow \u2014 the site no longer claims this hostname", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "helpjuice": { + "regex": "\\.helpjuice\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in Helpjuice \u2014 the knowledge base no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "helpscout": { + "regex": "\\.helpscoutdocs\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in Help Scout \u2014 the docs site no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "cargo_collective": { + "regex": "\\.cargocollective\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Cargo Collective site no longer exists and the name can be claimed", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "uservoice": { + "regex": "\\.uservoice\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in UserVoice \u2014 the forum no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "tilda": { + "regex": "\\.tilda\\.ws\\.", + "recommendation": "Delete the CNAME or re-add the domain in Tilda \u2014 the project no longer claims this hostname", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "bigcartel": { + "regex": "\\.bigcartel\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Big Cartel store no longer exists and the subdomain can be claimed", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "campaign_monitor": { + "regex": "\\.createsend\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in Campaign Monitor \u2014 the client no longer claims it", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "intercom": { + "regex": "\\.custom\\.intercom\\.help\\.", + "recommendation": "Delete the CNAME or re-add the custom domain in Intercom \u2014 the help centre no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "thinkific": { + "regex": "\\.thinkific\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in Thinkific \u2014 the school no longer claims this hostname", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "canny": { + "regex": "\\.canny\\.io\\.", + "recommendation": "Delete the CNAME or re-add the domain in Canny \u2014 the board no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "kajabi": { + "regex": "\\.endpoint\\.mykajabi\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in Kajabi \u2014 the site no longer claims this hostname", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "gemfury": { + "regex": "\\.furyns\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Gemfury account no longer claims this hostname", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "frontify": { + "regex": "\\.frontify\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in Frontify \u2014 the style guide no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "aha": { + "regex": "\\.ideas\\.aha\\.io\\.", + "recommendation": "Delete the CNAME or re-add the domain in Aha! \u2014 the ideas portal no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "brightcove": { + "regex": "\\.brightcovegallery\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in Brightcove \u2014 the gallery no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "wishpond": { + "regex": "\\.wishpond\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Wishpond campaign no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "getresponse": { + "regex": "\\.gr8\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in GetResponse \u2014 the landing page no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "agile_crm": { + "regex": "\\.agilecrm\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Agile CRM domain is no longer claimed", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "readme_io": { + "regex": "\\.readme\\.io\\.", + "recommendation": "Delete the CNAME or re-add the domain in ReadMe \u2014 the docs project no longer claims it", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "hatenablog": { + "regex": "\\.hatenablog\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Hatena Blog no longer exists and the name can be claimed", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "smugmug": { + "regex": "\\.domains\\.smugmug\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in SmugMug \u2014 the gallery no longer claims it", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "surveygizmo": { + "regex": "\\.privatedomain\\.sgizmo\\.com\\.", + "recommendation": "Delete the CNAME or re-add the domain in SurveyGizmo/Alchemer \u2014 it is no longer claimed", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "feedpress": { + "regex": "\\.redirect\\.feedpress\\.me\\.", + "recommendation": "Delete the CNAME or re-add the domain in FeedPress \u2014 the feed no longer claims it", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "simplebooklet": { + "regex": "\\.simplebooklet\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Simplebooklet no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "vend": { + "regex": "\\.vendhq\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Vend store no longer claims this hostname", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "jetbrains": { + "regex": "\\.myjetbrains\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the JetBrains YouTrack instance no longer claims this hostname", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "kinsta": { + "regex": "\\.kinsta\\.cloud\\.", + "recommendation": "Delete the CNAME or re-add the domain in Kinsta \u2014 the site no longer claims this hostname", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "short_io": { + "regex": "\\.cname\\.short\\.io\\.", + "recommendation": "Delete the CNAME or re-add the domain in Short.io \u2014 the link domain is no longer claimed", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" + }, + "pingdom": { + "regex": "\\.stats\\.pingdom\\.com\\.", + "recommendation": "Delete the CNAME \u2014 the Pingdom public status page no longer exists", + "evidence": "https://github.com/EdOverflow/can-i-take-over-xyz" } + } } diff --git a/tests/test_domain_categorisation_patterns.py b/tests/test_domain_categorisation_patterns.py new file mode 100644 index 0000000..973fc46 --- /dev/null +++ b/tests/test_domain_categorisation_patterns.py @@ -0,0 +1,103 @@ +""" +Tests for the takeover fingerprints in config.json. + +These guard the pattern set itself rather than the matching code. A fingerprint +that silently stops matching leaves a real takeover candidate reported as +'unknown', which is exactly the outcome the pattern set exists to prevent. + +Matching is first-match-wins, so these also catch a new pattern shadowing an +existing one. +""" + +import json +import os + +import pytest + +from classes.domain_categoriser import DomainCategoriser + +REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + + +@pytest.fixture(scope="module") +def patterns(): + with open(os.path.join(REPO_ROOT, "config.json"), encoding="utf-8") as f: + return json.load(f)["domain_categorisation"] + + +# One representative target per fingerprint. Kept explicit rather than generated +# from the regex, so a broken regex cannot make its own test pass. +SAMPLES = [ + ("app.herokuapp.com.", "heroku"), + ("user.github.io.", "github"), + ("lb-1234.eu-west-2.elb.amazonaws.com.", "aws_elb"), + ("bucket.s3.amazonaws.com.", "aws_s3"), + ("site.azurewebsites.net.", "azure"), + ("x.impervadns.net.", "incapsula"), + ("x.proxy-ssl.webflow.com.", "webflow"), + ("x.helpjuice.com.", "helpjuice"), + ("x.helpscoutdocs.com.", "helpscout"), + ("x.cargocollective.com.", "cargo_collective"), + ("x.uservoice.com.", "uservoice"), + ("x.tilda.ws.", "tilda"), + ("x.bigcartel.com.", "bigcartel"), + ("x.createsend.com.", "campaign_monitor"), + ("x.custom.intercom.help.", "intercom"), + ("x.thinkific.com.", "thinkific"), + ("x.canny.io.", "canny"), + ("x.endpoint.mykajabi.com.", "kajabi"), + ("x.furyns.com.", "gemfury"), + ("x.frontify.com.", "frontify"), + ("x.ideas.aha.io.", "aha"), + ("x.brightcovegallery.com.", "brightcove"), + ("x.wishpond.com.", "wishpond"), + ("x.gr8.com.", "getresponse"), + ("x.agilecrm.com.", "agile_crm"), + ("x.readme.io.", "readme_io"), + ("x.hatenablog.com.", "hatenablog"), + ("x.domains.smugmug.com.", "smugmug"), + ("x.privatedomain.sgizmo.com.", "surveygizmo"), + ("x.redirect.feedpress.me.", "feedpress"), + ("x.simplebooklet.com.", "simplebooklet"), + ("x.vendhq.com.", "vend"), + ("x.myjetbrains.com.", "jetbrains"), + ("x.kinsta.cloud.", "kinsta"), + ("x.cname.short.io.", "short_io"), + ("x.stats.pingdom.com.", "pingdom"), +] + + +@pytest.mark.parametrize("target,expected", SAMPLES) +def test_target_classifies_to_expected_category(target, expected, patterns): + category, _, _ = DomainCategoriser.categorise_domain(target, patterns) + assert category == expected, ( + f"{target} classified as '{category}', expected '{expected}' — " + "a pattern is missing, broken, or shadowed by an earlier one" + ) + + +def test_unrecognised_target_is_unknown(patterns): + """An unmatched target must be reported honestly, not guessed at.""" + category, recommendation, _ = DomainCategoriser.categorise_domain( + "something.entirely-unrecognised-xyzzy.example.", patterns + ) + assert category == "unknown" + assert recommendation == "Unclassified" + + +def test_every_pattern_is_well_formed(patterns): + """Each fingerprint must carry the three fields the output line depends on.""" + for name, entry in patterns.items(): + assert "regex" in entry, f"{name} has no regex" + assert entry.get("recommendation"), f"{name} has no recommendation" + assert entry.get("evidence"), f"{name} has no evidence link" + + +def test_every_pattern_compiles(patterns): + import re + + for name, entry in patterns.items(): + try: + re.compile(entry["regex"]) + except re.error as e: + pytest.fail(f"{name} has an invalid regex: {e}")