From 353d45c2bc583d5816125c0e15493ab9c141523c Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Thu, 25 Jun 2026 14:14:42 -0400 Subject: [PATCH 1/5] fix(stdlib): Gate url.full and http.query behind send_default_pii Gate URL_FULL, URL_QUERY, and HTTP_QUERY span attributes behind send_default_pii in the stdlib (httplib) integration, consistent with the aiohttp and wsgi integrations. Tests are updated to pass send_default_pii=True where they assert on those attributes, and the proxy tunnel test is expanded to cover both pii=True and pii=False. Co-Authored-By: Claude Sonnet 4.6 --- sentry_sdk/integrations/stdlib.py | 14 ++++--- tests/integrations/requests/test_requests.py | 4 +- tests/integrations/stdlib/test_httplib.py | 41 ++++++++++++++------ 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index 4e813a8345..0ce27a288b 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -8,7 +8,7 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import Integration -from sentry_sdk.scope import add_global_event_processor +from sentry_sdk.scope import add_global_event_processor, should_send_default_pii from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing import Span from sentry_sdk.tracing_utils import ( @@ -125,9 +125,10 @@ def putrequest( ) if parsed_url is not None: - span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) - span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) - span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) + if should_send_default_pii(): + span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) + span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) + span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) set_on_span = span.set_attribute @@ -141,9 +142,10 @@ def putrequest( span.set_data(SPANDATA.HTTP_METHOD, method) if parsed_url is not None: - span.set_data("url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) + if should_send_default_pii(): + span.set_data("url", parsed_url.url) + span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) set_on_span = span.set_data diff --git a/tests/integrations/requests/test_requests.py b/tests/integrations/requests/test_requests.py index 8cfc0f932f..17d5895918 100644 --- a/tests/integrations/requests/test_requests.py +++ b/tests/integrations/requests/test_requests.py @@ -13,7 +13,7 @@ def test_crumb_capture(sentry_init, capture_events): - sentry_init(integrations=[StdlibIntegration()]) + sentry_init(integrations=[StdlibIntegration()], send_default_pii=True) events = capture_events() url = f"http://localhost:{PORT}/hello-world" # noqa:E231 @@ -51,7 +51,7 @@ def test_crumb_capture(sentry_init, capture_events): ], ) def test_crumb_capture_client_error(sentry_init, capture_events, status_code, level): - sentry_init(integrations=[StdlibIntegration()]) + sentry_init(integrations=[StdlibIntegration()], send_default_pii=True) events = capture_events() diff --git a/tests/integrations/stdlib/test_httplib.py b/tests/integrations/stdlib/test_httplib.py index 0ad5fb5f95..3cfc247c39 100644 --- a/tests/integrations/stdlib/test_httplib.py +++ b/tests/integrations/stdlib/test_httplib.py @@ -77,7 +77,7 @@ def create_chunked_server(): def test_crumb_capture(sentry_init, capture_events): - sentry_init(integrations=[StdlibIntegration()]) + sentry_init(integrations=[StdlibIntegration()], send_default_pii=True) events = capture_events() url = "http://localhost:{}/some/random/url".format(PORT) @@ -113,7 +113,7 @@ def test_crumb_capture(sentry_init, capture_events): ], ) def test_crumb_capture_client_error(sentry_init, capture_events, status_code, level): - sentry_init(integrations=[StdlibIntegration()]) + sentry_init(integrations=[StdlibIntegration()], send_default_pii=True) events = capture_events() url = f"http://localhost:{PORT}/status/{status_code}" # noqa:E231 @@ -151,7 +151,11 @@ def before_breadcrumb(crumb, hint): crumb["data"]["extra"] = "foo" return crumb - sentry_init(integrations=[StdlibIntegration()], before_breadcrumb=before_breadcrumb) + sentry_init( + integrations=[StdlibIntegration()], + before_breadcrumb=before_breadcrumb, + send_default_pii=True, + ) events = capture_events() url = "http://localhost:{}/some/random/url".format(PORT) @@ -203,7 +207,7 @@ def test_httplib_misuse(sentry_init, capture_events, request): wrongly. """ - sentry_init() + sentry_init(send_default_pii=True) events = capture_events() conn = HTTPConnection("localhost", PORT) @@ -1136,15 +1140,18 @@ def test_http_timeout( @pytest.mark.parametrize("tunnel_port", [8080, None]) @pytest.mark.parametrize("span_streaming", [True, False]) +@pytest.mark.parametrize("send_default_pii", [True, False]) def test_proxy_http_tunnel( sentry_init, capture_events, capture_items, tunnel_port, span_streaming, + send_default_pii, ): sentry_init( traces_sample_rate=1.0, + send_default_pii=send_default_pii, _experiments={"trace_lifecycle": "stream" if span_streaming else "static"}, ) @@ -1154,7 +1161,7 @@ def test_proxy_http_tunnel( with sentry_sdk.traces.start_span(name="custom parent"): conn = HTTPConnection("localhost", PROXY_PORT) conn.set_tunnel("api.example.com", tunnel_port) - conn.request("GET", "/foo") + conn.request("GET", "/foo?bar=1") conn.getresponse() sentry_sdk.flush() @@ -1167,20 +1174,26 @@ def test_proxy_http_tunnel( port_modifier = f":{tunnel_port}" if tunnel_port else "" assert span["name"] == f"GET http://api.example.com{port_modifier}/foo" - assert ( - span["attributes"][SPANDATA.URL_FULL] - == f"http://api.example.com{port_modifier}/foo" - ) assert span["attributes"][SPANDATA.HTTP_REQUEST_METHOD] == "GET" assert span["attributes"][SPANDATA.NETWORK_PEER_ADDRESS] == "localhost" assert span["attributes"][SPANDATA.NETWORK_PEER_PORT] == PROXY_PORT + + if send_default_pii: + assert ( + span["attributes"][SPANDATA.URL_FULL] + == f"http://api.example.com{port_modifier}/foo" + ) + assert span["attributes"][SPANDATA.URL_QUERY] == "bar=1" + else: + assert SPANDATA.URL_FULL not in span["attributes"] + assert SPANDATA.URL_QUERY not in span["attributes"] else: events = capture_events() with start_transaction(name="test_transaction"): conn = HTTPConnection("localhost", PROXY_PORT) conn.set_tunnel("api.example.com", tunnel_port) - conn.request("GET", "/foo") + conn.request("GET", "/foo?bar=1") conn.getresponse() (event,) = events @@ -1188,11 +1201,17 @@ def test_proxy_http_tunnel( port_modifier = f":{tunnel_port}" if tunnel_port else "" assert span["description"] == f"GET http://api.example.com{port_modifier}/foo" - assert span["data"]["url"] == f"http://api.example.com{port_modifier}/foo" assert span["data"][SPANDATA.HTTP_METHOD] == "GET" assert span["data"][SPANDATA.NETWORK_PEER_ADDRESS] == "localhost" assert span["data"][SPANDATA.NETWORK_PEER_PORT] == PROXY_PORT + if send_default_pii: + assert span["data"]["url"] == f"http://api.example.com{port_modifier}/foo" + assert span["data"][SPANDATA.HTTP_QUERY] == "bar=1" + else: + assert "url" not in span["data"] + assert SPANDATA.HTTP_QUERY not in span["data"] + @pytest.mark.parametrize("span_streaming", [True, False]) def test_chunked_response_span_covers_body_read( From 94078a1e9bfd88e55ea1ad88e5be7f09a031c285 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Thu, 25 Jun 2026 14:18:58 -0400 Subject: [PATCH 2/5] cleanup --- sentry_sdk/integrations/stdlib.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index 0ce27a288b..408bff7602 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -124,11 +124,10 @@ def putrequest( }, ) - if parsed_url is not None: - if should_send_default_pii(): - span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) - span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) - span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) + if parsed_url is not None and should_send_default_pii(): + span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) + span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) + span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) set_on_span = span.set_attribute From 10d09af880fef1c874ba83fe98592dd4a18f0d5c Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Thu, 25 Jun 2026 14:20:18 -0400 Subject: [PATCH 3/5] . --- sentry_sdk/integrations/stdlib.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index 408bff7602..e863202ec6 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -140,11 +140,10 @@ def putrequest( ) span.set_data(SPANDATA.HTTP_METHOD, method) - if parsed_url is not None: + if parsed_url is not None and should_send_default_pii(): span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - if should_send_default_pii(): - span.set_data("url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) + span.set_data("url", parsed_url.url) + span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) set_on_span = span.set_data From 754067bcdffcbd200160922469c3269b1fa1ada8 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Thu, 25 Jun 2026 14:27:28 -0400 Subject: [PATCH 4/5] m --- sentry_sdk/integrations/stdlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index e863202ec6..82f30f2dda 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -140,7 +140,7 @@ def putrequest( ) span.set_data(SPANDATA.HTTP_METHOD, method) - if parsed_url is not None and should_send_default_pii(): + if parsed_url is not None: span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) span.set_data("url", parsed_url.url) span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) From 0f7cab67e089ab2a4d8e7a4f9fdb22d97855a786 Mon Sep 17 00:00:00 2001 From: Erica Pisani Date: Thu, 25 Jun 2026 14:41:20 -0400 Subject: [PATCH 5/5] . --- tests/integrations/stdlib/test_httplib.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/integrations/stdlib/test_httplib.py b/tests/integrations/stdlib/test_httplib.py index 3cfc247c39..1723830f4e 100644 --- a/tests/integrations/stdlib/test_httplib.py +++ b/tests/integrations/stdlib/test_httplib.py @@ -1204,13 +1204,8 @@ def test_proxy_http_tunnel( assert span["data"][SPANDATA.HTTP_METHOD] == "GET" assert span["data"][SPANDATA.NETWORK_PEER_ADDRESS] == "localhost" assert span["data"][SPANDATA.NETWORK_PEER_PORT] == PROXY_PORT - - if send_default_pii: - assert span["data"]["url"] == f"http://api.example.com{port_modifier}/foo" - assert span["data"][SPANDATA.HTTP_QUERY] == "bar=1" - else: - assert "url" not in span["data"] - assert SPANDATA.HTTP_QUERY not in span["data"] + assert span["data"]["url"] == f"http://api.example.com{port_modifier}/foo" + assert span["data"][SPANDATA.HTTP_QUERY] == "bar=1" @pytest.mark.parametrize("span_streaming", [True, False])