Skip to content

fix(httpx2): Gate url.full, url.query on send_default_pii#6670

Merged
ericapisani merged 1 commit into
masterfrom
py-2559-httpx2-pii-gating
Jun 26, 2026
Merged

fix(httpx2): Gate url.full, url.query on send_default_pii#6670
ericapisani merged 1 commit into
masterfrom
py-2559-httpx2-pii-gating

Conversation

@ericapisani

@ericapisani ericapisani commented Jun 25, 2026

Copy link
Copy Markdown
Member

url.full and url.query can contain sensitive data such as query parameters or credentials embedded in URLs. This gates both attributes behind send_default_pii in the httpx2 integration, matching the behavior already in place for aiohttp and wsgi.

Fixes PY-2559
Fixes #6669

url.full and url.query can contain sensitive data (query strings, credentials
in URLs). Gate these attributes behind send_default_pii to match the behavior
of the aiohttp and wsgi integrations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jun 25, 2026

Copy link
Copy Markdown

PY-2559

@ericapisani ericapisani marked this pull request as ready for review June 25, 2026 18:53
@ericapisani ericapisani requested a review from a team as a code owner June 25, 2026 18:53
@@ -73,7 +74,7 @@ def send(self: "Client", request: "Request", **kwargs: "Any") -> "Response":
) as streamed_span:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PII gate not applied to default non-streaming path — URL, query, and fragment still exposed

The should_send_default_pii() guard added in this PR only protects the experimental span-streaming path (is_span_streaming_enabled). The non-streaming else branch — which is the DEFAULT code path since streaming requires opting in via _experiments.trace_lifecycle == "stream" — still calls span.set_data("url", parsed_url.url), span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query), and span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) gated only on parsed_url is not None. As a result, query parameters and credentials embedded in URLs are still recorded in spans for most users even when send_default_pii=False, so the PR does not achieve its stated goal on the default path. The same gap exists in both _install_httpx2_client and _install_httpx2_async_client.

Evidence
  • has_span_streaming_enabled in tracing_utils.py returns true only when _experiments.trace_lifecycle == "stream", so the else (non-streaming) branch is the default path for most users.
  • In _install_httpx2_client's else branch (httpx2.py:122-126) span.set_data("url", ...), span.set_data(SPANDATA.HTTP_QUERY, ...), and span.set_data(SPANDATA.HTTP_FRAGMENT, ...) are gated only on parsed_url is not None, with no should_send_default_pii() check.
  • The streaming branch above (httpx2.py:77) does add the should_send_default_pii() guard, confirming the gate was applied to only one of the two paths.
  • _install_httpx2_async_client's else branch (httpx2.py:232-235) repeats the same ungated set_data calls.

Identified by Warden code-review · PJJ-2ZL

Comment on lines 74 to 80
) as streamed_span:
attributes: "Attributes" = {}

if parsed_url is not None:
if parsed_url is not None and should_send_default_pii():
attributes["url.full"] = parsed_url.url
if parsed_url.query:
attributes["url.query"] = parsed_url.query

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The non-streaming path for httpx2 requests unconditionally adds URL data to spans, ignoring the send_default_pii setting.
Severity: MEDIUM

Suggested Fix

Wrap the span.set_data calls for URL and query parameters in the non-streaming paths (both sync and async) with a if should_send_default_pii(): check. This will ensure consistent PII handling across both streaming and non-streaming modes.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: sentry_sdk/integrations/httpx2.py#L74-L80

Potential issue: The change to gate URL data behind `should_send_default_pii()` was only
applied to the streaming span path in the `httpx2` integration. The non-streaming path,
for both synchronous and asynchronous requests, still unconditionally sets
`span.set_data("url", ...)` and `span.set_data(SPANDATA.HTTP_QUERY, ...)` without
checking the PII setting. This means that even if a user configures
`send_default_pii=False` to prevent sending sensitive information like query parameters,
this data will still be sent for non-streaming `httpx` requests, leading to a potential
PII leak.

Also affects:

  • sentry_sdk/integrations/httpx2.py:184~190

Did we get this right? 👍 / 👎 to inform future reviews.

@github-actions

Copy link
Copy Markdown
Contributor

Codecov Results 📊

89935 passed | ⏭️ 6240 skipped | Total: 96175 | Pass Rate: 93.51% | Execution Time: 318m 47s

📊 Comparison with Base Branch

Metric Change
Total Tests 📈 +30
Passed Tests 📈 +30
Failed Tests
Skipped Tests

All tests are passing successfully.

✅ Patch coverage is 100.00%. Project has 2396 uncovered lines.
✅ Project coverage is 89.93%. Comparing base (base) to head (head).

Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    89.93%    89.93%        —%
==========================================
  Files          192       192         —
  Lines        23784     23785        +1
  Branches      8210      8210         —
==========================================
+ Hits         21389     21389         —
- Misses        2395      2396        +1
- Partials      1342      1341        -1

Generated by Codecov Action

@ericapisani ericapisani merged commit 2545570 into master Jun 26, 2026
144 checks passed
@ericapisani ericapisani deleted the py-2559-httpx2-pii-gating branch June 26, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gate url.full behind the PII flag in httpx2

2 participants