feat(wsgi): Apply data_collection filtering to URL query strings#6827
Conversation
…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
… _experiments property in the client
…still being needed for the url attribute
…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
… _experiments property in the client
…still being needed for the url attribute
…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.
…into py-2581-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
Codecov Results 📊✅ 93595 passed | ⏭️ 6304 skipped | Total: 99899 | Pass Rate: 93.69% | Execution Time: 326m 13s 📊 Comparison with Base Branch
All tests are passing successfully. ✅ Patch coverage is 100.00%. Project has 2479 uncovered lines. Files with missing lines (1)
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 +3Generated by Codecov Action |
|
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
sentrivana
left a comment
There was a problem hiding this comment.
One concern regarding query string reassembly, otherwise looking great!
| items=parsed_qs, behaviour=behaviour | ||
| ) | ||
|
|
||
| if filtered_qs: |
There was a problem hiding this comment.
We should probably use urlencode for the reassembly. Query strings can be finicky so it'd be safer to rely on the stdlib here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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) |
There was a problem hiding this comment.
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.
Reviewed by Cursor Bugbot for commit 7f12491. Configure here.
There was a problem hiding this comment.
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.


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