Skip to content

fix(gql): Remove credentials and query values from the transport URL - #8227

Open
Mohil-Ahuja wants to merge 2 commits into
getsentry:masterfrom
Mohil-Ahuja:fix/gql-sanitize-transport-url
Open

Mohil-Ahuja wants to merge 2 commits into
getsentry:masterfrom
Mohil-Ahuja:fix/gql-sanitize-transport-url

Conversation

@Mohil-Ahuja

Copy link
Copy Markdown

Description

The gql integration copied transport.url into event["request"]["url"] unchanged, so credentials and query tokens in the URL were sent with every event, whatever send_default_pii was set to.

The URL now goes through parse_url. The authority is filtered in url, and the query goes to query_string.

One change from what I suggested in the issue: I kept parse_url's default sanitizing instead of sanitize=False. With sanitize=False, a token such as access_token=... would only move from url to query_string and still be sent. Query values are now always [Filtered], with the keys kept, even with send_default_pii=True. If you'd rather keep the values when PII is enabled, that's a small change.

The URL is passed through str() because some transports accept a URL object as well as a string. If parsing fails, url is left out of the event.

I ran tests/integrations/gql through tox on py3.10-gql-v3.4.1, py3.14-gql-v4.4.0 and py3.14-gql-latest, plus ruff and mypy. Without the change, the new sanitizing tests fail.

Issues

The integration copied transport.url into event["request"]["url"] unchanged,
so credentials and query tokens in the URL were sent with every event, whatever
send_default_pii was set to. Sanitize it with parse_url and send the filtered
query in query_string.
@Mohil-Ahuja
Mohil-Ahuja marked this pull request as ready for review November 9, 2026 09:35
@Mohil-Ahuja
Mohil-Ahuja requested a review from a team as a code owner November 9, 2026 09:35

@sentrivana sentrivana left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hey @Mohil-Ahuja, thanks for the PR. One thing that I'm missing is support for data_collection -- that's an SDK option that will supersede send_default_pii in the next major. At the moment, we need to support both data_collection and send_default_pii (data_collection takes precedence, if provided).

There are two places where I'm missing data_collection support:

  1. In the integration itself, when attaching query_string. data_collection has a setting called url_query_params (https://docs.sentry.io/platforms/python/data-management/data-collected/#request-query-string) which controls whether to attach the query and if so, what to omit from it.
  2. In the test, we only parametrize based on send_default_pii; we need to parametrize based on different data_collection options as well. Check out similar tests for inspiration.

Also, I believe we just need one test case, parametrized on the different send_default_pii and data_collection configs, based on test_transport_url_is_sanitized; no need for the other test cases.

@Mohil-Ahuja

Copy link
Copy Markdown
Author

@sentrivana thanks, updated in cfb50c6. When data_collection is set, the URL is parsed without sanitizing the query and url_query_params is applied to it, the same way the other integrations handle query_string, so off drops it and denylist/allowlist filter it. Without data_collection the behaviour is as before: credentials removed and query values replaced with [Filtered].

The other test cases are gone. test_transport_url_is_sanitized is now parametrized on no options, send_default_pii=True, data_collection defaults, off, a denylist, an allowlist, and data_collection taking precedence over send_default_pii. The credentials are removed from the URL in every case.

This branch has not been deployed

No deployments
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.

gql: transport URL is sent as request.url without removing credentials

2 participants