Skip to content

feat(wsgi): Apply data_collection filtering to URL query strings#6827

Merged
ericapisani merged 35 commits into
masterfrom
py-2583-query-parameters
Jul 22, 2026
Merged

feat(wsgi): Apply data_collection filtering to URL query strings#6827
ericapisani merged 35 commits into
masterfrom
py-2583-query-parameters

Conversation

@ericapisani

@ericapisani ericapisani commented Jul 15, 2026

Copy link
Copy Markdown
Member

Filter WSGI request event and span query strings through the
data_collection.url_query_params behaviour (denylist/allowlist/off)
instead of gating query string capture solely on send_default_pii.
This brings WSGI-based integrations in line with the data collection
spec's handling of cookies and headers.

Rename the data_collection field query_params to url_query_params to
match the updated data collection spec, which distinguishes URL query
params from other key-value data (cookies, headers). Update the
DataCollection/DataCollectionUserOptions TypedDicts, resolution logic
in data_collection.py, and all WSGI/Flask/Django test coverage
accordingly.

Refs PY-2583

…n config

`_filter_headers` previously used a hardcoded sensitive-header tuple and a
`send_default_pii`/`use_annotated_value` toggle. It now delegates to
`_apply_key_value_collection_filtering` from `sentry_sdk.data_collection`,
so header scrubbing respects the new `data_collection.http_headers.request`
allowlist/denylist/off configuration.

Cookie and set-cookie headers are
always redacted regardless of mode. Drops the now-unused
`use_annotated_value` parameter from all call sites.

Work to scrub cookies in a more granular way will be tackled as part of
PY-2581/#6741.

Fixes PY-2584
Fixes #6744
…ures

The new lambda_functions_with_embedded_sdk fixture directories were
missing the .gitignore that the other fixtures use to keep everything
except index.py untracked. As a result, certifi and urllib3 packages
installed by the test setup got committed, and ruff failed CI linting
against them since they're unmodified third-party code.

Add the missing .gitignore to each new fixture directory and remove
the committed vendored packages; they are regenerated automatically at
test time via `uv pip install --target`.
…tarlette, litestar, starlite

Extends the granular cookie collection controls (data_collection.cookies)
to _wsgi_common, starlette, litestar, and starlite, matching the behavior
already used elsewhere. Falls back to should_send_default_pii() when
data_collection is not configured for cookies.

HTTP "Cookie" and "set-cookie" headers will continue to be completely filtered
with the "[Filtered]" value.

Fixes PY-2581
Fixes #6741
…de is off

Previously the async request extractors attached an empty cookies dict
when the data_collection cookies mode was off, while sync route handlers
omitted it entirely. Make all integrations consistent by not attaching
the cookies field at all when filtering yields no cookies.
…n config

`_filter_headers` previously used a hardcoded sensitive-header tuple and a
`send_default_pii`/`use_annotated_value` toggle. It now delegates to
`_apply_key_value_collection_filtering` from `sentry_sdk.data_collection`,
so header scrubbing respects the new `data_collection.http_headers.request`
allowlist/denylist/off configuration.

Cookie and set-cookie headers are
always redacted regardless of mode. Drops the now-unused
`use_annotated_value` parameter from all call sites.

Work to scrub cookies in a more granular way will be tackled as part of
PY-2581/#6741.

Fixes PY-2584
Fixes #6744
…ures

The new lambda_functions_with_embedded_sdk fixture directories were
missing the .gitignore that the other fixtures use to keep everything
except index.py untracked. As a result, certifi and urllib3 packages
installed by the test setup got committed, and ruff failed CI linting
against them since they're unmodified third-party code.

Add the missing .gitignore to each new fixture directory and remove
the committed vendored packages; they are regenerated automatically at
test time via `uv pip install --target`.
…ntry/sentry-python into py-2584-update-wsgi-filter-headers
…tarlette, litestar, starlite

Extends the granular cookie collection controls (data_collection.cookies)
to _wsgi_common, starlette, litestar, and starlite, matching the behavior
already used elsewhere. Falls back to should_send_default_pii() when
data_collection is not configured for cookies.

HTTP "Cookie" and "set-cookie" headers will continue to be completely filtered
with the "[Filtered]" value.

Fixes PY-2581
Fixes #6741
…de is off

Previously the async request extractors attached an empty cookies dict
when the data_collection cookies mode was off, while sync route handlers
omitted it entirely. Make all integrations consistent by not attaching
the cookies field at all when filtering yields no cookies.
The streaming path no longer emits a client span when there is no current
span (#6810), so unpack only the server span.
Filter WSGI request event and span query strings through the
data_collection.url_query_params behaviour (denylist/allowlist/off)
instead of gating query string capture solely on send_default_pii.
This brings WSGI-based integrations in line with the data collection
spec's handling of cookies and headers.

Rename the data_collection field query_params to url_query_params to
match the updated data collection spec, which distinguishes URL query
params from other key-value data (cookies, headers). Update the
DataCollection/DataCollectionUserOptions TypedDicts, resolution logic
in data_collection.py, and all WSGI/Flask/Django test coverage
accordingly.

Refs PY-2583
@linear-code

linear-code Bot commented Jul 15, 2026

Copy link
Copy Markdown

PY-2583

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

93595 passed | ⏭️ 6304 skipped | Total: 99899 | Pass Rate: 93.69% | Execution Time: 326m 13s

📊 Comparison with Base Branch

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

All tests are passing successfully.

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

Files with missing lines (1)
File Patch % Lines
sentry_sdk/integrations/wsgi.py 100.00% ⚠️ 2 partials
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    89.72%    89.73%    +0.01%
==========================================
  Files          193       193         —
  Lines        24103     24127       +24
  Branches      8402      8418       +16
==========================================
+ Hits         21625     21648       +23
- Misses        2478      2479        +1
- Partials      1388      1391        +3

Generated by Codecov Action

@ericapisani
ericapisani marked this pull request as ready for review July 15, 2026 20:19
@ericapisani
ericapisani requested a review from a team as a code owner July 15, 2026 20:19
@ericapisani
ericapisani marked this pull request as draft July 16, 2026 15:41
@ericapisani

Copy link
Copy Markdown
Member Author

Moving this back to draft as, on looking at the spec again, the query parameters are not supposed to appear URL encoded in the attributes

…orm with what is shown in the data collection spec
@ericapisani
ericapisani marked this pull request as ready for review July 16, 2026 16:01
Comment thread sentry_sdk/integrations/wsgi.py
Comment thread sentry_sdk/data_collection.py
Comment thread sentry_sdk/integrations/wsgi.py

@sentrivana sentrivana left a comment

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.

One concern regarding query string reassembly, otherwise looking great!

items=parsed_qs, behaviour=behaviour
)

if filtered_qs:

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.

We should probably use urlencode for the reassembly. Query strings can be finicky so it'd be safer to rely on the stdlib here.

Base automatically changed from py-2581-cookies to master July 22, 2026 15:47
Comment thread sentry_sdk/data_collection.py

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7f12491. Configure here.

)

if filtered_qs:
return urlencode(filtered_qs, doseq=True)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Query string left URL-encoded

High Severity

_apply_data_collection_filtering_to_query_string reassembles with urlencode only, so filtered query strings stay URL-encoded (e.g. [Filtered] becomes %5BFiltered%5D). The data collection spec and existing sanitize_url pattern expect decoded values; ASGI already emits decoded query strings via unquote.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7f12491. Configure here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This was done to address #6827 (comment) . I'll be following up with the wider team to understand if the data collection spec needs to be updated.

@ericapisani
ericapisani merged commit c0f2100 into master Jul 22, 2026
141 checks passed
@ericapisani
ericapisani deleted the py-2583-query-parameters branch July 22, 2026 17:05
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.

2 participants