Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions sentry_sdk/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1823,14 +1823,31 @@ def match_regex_list(

def is_sentry_url(client: "sentry_sdk.client.BaseClient", url: str) -> bool:
"""
Determines whether the given URL matches the Sentry DSN.
Determines whether the given URL's hostname matches the Sentry DSN.

``url`` may be an absolute URL or a raw host with an optional port.
"""
return (
client is not None
and client.transport is not None
and client.transport.parsed_dsn is not None
and client.transport.parsed_dsn.netloc in url
)
if (
client is None
or client.transport is None
or client.transport.parsed_dsn is None
):
return False

dsn_host = client.transport.parsed_dsn.host

# ``HTTPConnection.host`` is a raw hostname without brackets for IPv6.
if url.lower() == dsn_host.lower():
return True

candidate = url if "://" in url or url.startswith("//") else "//" + url

try:
hostname = urlsplit(candidate).hostname
except ValueError:
return False

return hostname is not None and hostname.lower() == dsn_host.lower()


def _generate_installed_modules() -> "Iterator[Tuple[str, str]]":
Expand Down
38 changes: 31 additions & 7 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,15 +882,15 @@ class TestIntegration(Integration):


@pytest.fixture
def mock_client_with_dsn_netloc():
def mock_client_with_dsn():
"""
Returns a mocked Client with a DSN netloc of "abcd1234.ingest.sentry.io".
Returns a mocked Client with a DSN host of "abcd1234.ingest.sentry.io".
"""
mock_client = mock.Mock(spec=sentry_sdk.Client)
mock_client.transport = mock.Mock(spec=sentry_sdk.Transport)
mock_client.transport.parsed_dsn = mock.Mock(spec=Dsn)

mock_client.transport.parsed_dsn.netloc = "abcd1234.ingest.sentry.io"
mock_client.transport.parsed_dsn.host = "abcd1234.ingest.sentry.io"

return mock_client

Expand All @@ -899,13 +899,37 @@ def mock_client_with_dsn_netloc():
["test_url", "is_sentry_url_expected"],
[
["https://asdf@abcd1234.ingest.sentry.io/123456789", True],
["HTTP://ABCD1234.INGEST.SENTRY.IO:8443/envelope", True],
["abcd1234.ingest.sentry.io", True],
["abcd1234.ingest.sentry.io:9000", True],
["https://asdf@abcd1234.ingest.notsentry.io/123456789", False],
["https://abcd1234.ingest.sentry.io.evil.test/api/1", False],
["https://abcd1234.ingest.sentry.io@attacker.test/api/1", False],
["https://attacker.test/abcd1234.ingest.sentry.io", False],
["https://attacker.test/?next=abcd1234.ingest.sentry.io", False],
["abcd1234.ingest.sentry.io.evil.test", False],
["https://[::1", False],
],
)
def test_is_sentry_url_true(
test_url, is_sentry_url_expected, mock_client_with_dsn_netloc
):
ret_val = is_sentry_url(mock_client_with_dsn_netloc, test_url)
def test_is_sentry_url(test_url, is_sentry_url_expected, mock_client_with_dsn):
ret_val = is_sentry_url(mock_client_with_dsn, test_url)

assert ret_val == is_sentry_url_expected


@pytest.mark.parametrize(
["test_url", "is_sentry_url_expected"],
[
["2001:db8::1", True],
["[2001:db8::1]:9000", True],
["HTTP://[2001:DB8::1]:9000/envelope", True],
["http://[2001:db8::2]:9000/envelope", False],
],
)
def test_is_sentry_url_ipv6(test_url, is_sentry_url_expected, mock_client_with_dsn):
mock_client_with_dsn.transport.parsed_dsn.host = "2001:db8::1"

ret_val = is_sentry_url(mock_client_with_dsn, test_url)

assert ret_val == is_sentry_url_expected

Expand Down
20 changes: 20 additions & 0 deletions tests/tracing/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,26 @@ def test_should_propagate_trace(
"http://squirrelchasers.ingest.sentry.io/12312012",
False,
),
(
"https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
"https://SQUIRRELCHASERS.INGEST.SENTRY.IO/12312012",
False,
),
(
"https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
"https://squirrelchasers.ingest.sentry.io.evil.test/12312012",
True,
),
(
"https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
"https://squirrelchasers.ingest.sentry.io@attacker.test/12312012",
True,
),
(
"https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
"https://attacker.test/?next=squirrelchasers.ingest.sentry.io",
True,
),
(
"https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012",
"http://ingest.sentry.io/12312012",
Expand Down