fix: only treat the base domain and its subdomains as internal - #2109
Open
eeshsaxena wants to merge 1 commit into
Open
fix: only treat the base domain and its subdomains as internal#2109eeshsaxena wants to merge 1 commit into
eeshsaxena wants to merge 1 commit into
Conversation
is_external_url decided membership with a bare url_domain.endswith(base), so any host that merely ends with the base string was classified as internal: notexample.com and malicious-example.com both counted as part of example.com. base_domain comes from get_base_domain(), so those are genuinely different sites an attacker can register, and the result feeds link classification and the deep-crawl scope check - a crawl scoped to one domain could follow links onto look-alike domains. Match what deep_crawling/filters.py and domain_mapper.py already do: internal means equal to the base domain or a dot-separated subdomain of it. Real subdomains (blog.example.com) and relative URLs are unchanged. The www. strip also moves from .replace("www.", "") to .removeprefix("www."), so a host with www. somewhere other than the front is not silently rewritten. Adds TestIsExternalUrl to tests/regression/test_reg_utils.py covering the base domain, a subdomain, www., the two look-alike cases, the base domain as a prefix, an unrelated domain, a relative URL, and a mailto: link.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
is_external_urldecided whether a link belongs to the site being crawled with a bare suffix check:Any host whose name merely ends with the base domain string passed that check and was classified as internal:
basecomes fromget_base_domain(), so it is a bare registrable domain and these are genuinely different sites an attacker can register. The result feeds link classification incontent_scraping_strategy.pyand the deep-crawl scope check indomain_mapper.py, so a crawl scoped to one domain could follow links onto look-alike domains.The fix matches what the rest of the codebase already does (
deep_crawling/filters.py,domain_mapper.py): internal means equal to the base domain, or a dot-separated subdomain of it (domain == base or domain.endswith(f".{base}")). Real subdomains (blog.example.com) and relative URLs are unchanged. Thewww.strip also moves from.replace("www.", "")to.removeprefix("www."), so a host containingwww.somewhere other than the front is not silently rewritten.No existing issue filed — happy to open one first if you'd prefer it tracked separately.
List of files changed and why
crawl4ai/utils.py— rewriteis_external_url's membership test fromendswith(base)to== base or endswith("." + base), and switch thewww.strip toremoveprefix.tests/regression/test_reg_utils.py— addTestIsExternalUrlcovering the base domain, a subdomain,www., the two look-alike cases (notexample.com,malicious-example.com), the base domain as a prefix, an unrelated domain, a relative URL, and amailto:link.How Has This Been Tested?
Ran
pytest tests/regression/test_reg_utils.py. Against the current code, the two look-alike cases in the newTestIsExternalUrlfail (demonstrating the bug); with the fix applied the full file passes.Checklist: