From 1309ab810ac3d6c795ebb9410b319c3a4fd2f3af Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Mon, 12 Oct 2026 11:35:26 +0200 Subject: [PATCH 1/2] docs: Update docs on parametrization and scrubbing --- .../client/data-collection/index.mdx | 16 ++- .../client/integrations/http-client.mdx | 2 +- .../sdk/foundations/data-scrubbing.mdx | 126 +++++++++++++++--- develop-docs/sdk/telemetry/metrics.mdx | 5 +- .../sdk/telemetry/traces/modules/queries.mdx | 34 ++++- .../sdk/telemetry/traces/structuring-data.mdx | 12 +- 6 files changed, 154 insertions(+), 41 deletions(-) diff --git a/develop-docs/sdk/foundations/client/data-collection/index.mdx b/develop-docs/sdk/foundations/client/data-collection/index.mdx index 7b203fc8c13d89..2c599c28faffde 100644 --- a/develop-docs/sdk/foundations/client/data-collection/index.mdx +++ b/develop-docs/sdk/foundations/client/data-collection/index.mdx @@ -2,12 +2,15 @@ title: Data Collection description: Configuration for what data SDKs collect by default, including technical context, PII, and sensitive data. spec_id: sdk/foundations/client/data-collection -spec_version: 0.15.0 +spec_version: 0.16.0 spec_status: candidate spec_depends_on: - id: sdk/foundations/client version: ">=1.0.0" spec_changelog: + - version: 0.16.0 + date: 2026-10-12 + summary: "Attach text bodies unchanged. SDKs no longer parse bodies to scrub them. Relay scrubs the body." - version: 0.15.0 date: 2026-09-29 summary: "Attach cookie headers as one string-array span attribute (`name=value` elements) instead of one attribute per cookie name. Filter nameless cookie segments and unparseable cookie strings." @@ -72,7 +75,8 @@ The new `dataCollection` configuration collects rich context for debugging by de Related specs: -- [Data Scrubbing](/sdk/foundations/data-scrubbing/) — structuring data for scrubbing (spans, breadcrumbs), variable size limits +- [Data Scrubbing](/sdk/foundations/data-scrubbing/) — which data the SDK scrubs, which data Relay scrubs, and parameterization +- [Variable Size](/sdk/foundations/envelopes/event-payloads/#variable-size) — size limits for variable-size data - [Client](/sdk/foundations/client/) — client lifecycle and event pipeline - [Configuration](/sdk/foundations/client/configuration/) — top-level init options including `send_default_pii` (deprecated in favor of this spec) @@ -222,7 +226,7 @@ init({ URL strings in span descriptions follow the format defined in [Structuring Data](/sdk/telemetry/traces/structuring-data/): `METHOD scheme://host/path` — query strings and fragments are excluded. -The `urlQueryParams` option controls query parameter filtering wherever query strings appear — including `url.full`, `url.query`, and [`request.query_string`](/sdk/foundations/envelopes/event-payloads/request/). `url.path` and the span description are unaffected since they never contain query strings. For general data scrubbing rules (variable size limits, structuring for server-side scrubbing), see [Data Scrubbing](/sdk/foundations/data-scrubbing/). +The `urlQueryParams` option controls query parameter filtering wherever query strings appear — including `url.full`, `url.query`, and [`request.query_string`](/sdk/foundations/envelopes/event-payloads/request/). `url.path` and the span description are unaffected since they never contain query strings. Encoded query parameters **MUST** be stored exactly as they appear in the URL. @@ -276,8 +280,8 @@ Unfiltered, raw cookie header values **MUST NOT** be sent. When in doubt, treat When bodies are collected via the `httpBodies` option (enabled by default; see [Body Type Collection](#body-type-collection)): -- **Parseable as JSON or form data:** SDKs **MAY** extract key-value pairs and apply the same denylist rules to keys. Values for matching keys **MUST** be replaced with `"[Filtered]"`. This allows selective scrubbing while retaining non-sensitive fields. -- **Not parseable (raw bodies):** The body **MUST NOT** be attached to the event. When the SDK cannot parse the body into a key-value structure, the entire body **MUST** be replaced with `"[Filtered]"`. +- **Text bodies:** SDKs **SHOULD** attach the body unchanged. SDKs **SHOULD NOT** parse the body to scrub it. Relay scrubs the body (see [Heuristic Scrubbing in Relay](/sdk/foundations/data-scrubbing/#heuristic-scrubbing)). +- **Bodies that the framework already parsed:** SDKs **MAY** apply the denylist to the keys. Values for matching keys **MUST** be replaced with `"[Filtered]"`. No built-in option scrubs **keys**; users who need to hide header or cookie names **MUST** use `beforeSend` (or equivalent). @@ -536,7 +540,7 @@ SDKs **MUST** support configuring body collection for specific body types. The o Valid body type values: `"incomingRequest"`, `"outgoingRequest"`, `"incomingResponse"`, `"outgoingResponse"`. Body collection **MAY** not support allow/deny filtering. Unlike cookies or headers, body content has no predictable key structure for the SDK to filter at collection time. -The entire body is either collected (and scrubbed based on the key **if parseable** as JSON or form data) or not. Body data can still be redacted in `beforeSend` or event processors if needed. +The entire body is either collected or not. For how SDKs and Relay scrub a collected body, see [Request and Response Bodies](#request-and-response-bodies). Body data can still be redacted in `beforeSend` or event processors if needed. diff --git a/develop-docs/sdk/foundations/client/integrations/http-client.mdx b/develop-docs/sdk/foundations/client/integrations/http-client.mdx index dfa162363a7cf1..151a7a2a1a7521 100644 --- a/develop-docs/sdk/foundations/client/integrations/http-client.mdx +++ b/develop-docs/sdk/foundations/client/integrations/http-client.mdx @@ -82,7 +82,7 @@ The HTTP Client integration should have 3 configuration options: - If the language has a `Range` type, it should be used instead of `HttpStatusCodeRange`. - `failedRequestTargets` defaults to (`.*`), this configuration option accepts a `List` of `String` that may be Regular expressions as well, similar to tracePropagationTargets. - The SDK will only capture HTTP Client errors if the HTTP Request URL is a match for any of the `failedRequestsTargets`. -- While the keys of sensitive HTTP headers (e.g. `Authorization` and `Cookie`) are included, their values must be replaced with `"[Filtered]"` (also see Data Handling: Sensitive Data). +- While the keys of sensitive HTTP headers (e.g. `Authorization` and `Cookie`) are included, their values must be replaced with `"[Filtered]"` (also see Data Collection: Sensitive Denylist). The HTTP Client integration should capture error events with the following properties: diff --git a/develop-docs/sdk/foundations/data-scrubbing.mdx b/develop-docs/sdk/foundations/data-scrubbing.mdx index 02280d210b9843..79affbf3a04d90 100644 --- a/develop-docs/sdk/foundations/data-scrubbing.mdx +++ b/develop-docs/sdk/foundations/data-scrubbing.mdx @@ -1,36 +1,124 @@ --- title: Data Scrubbing +description: Rules that decide which sensitive data the SDK removes, which sensitive data Relay removes, and how SDKs parameterize data. +spec_id: sdk/foundations/data-scrubbing +spec_version: 1.0.0 +spec_status: candidate +spec_depends_on: + - id: sdk/foundations/client/data-collection + version: ">=0.16.0" +spec_changelog: + - version: 1.0.0 + date: 2026-10-12 + summary: Initial spec. Define not collecting, parameterization, and scrubbing, and split the scrubbing work between SDKs and Relay. sidebar_order: 6 --- -Data handling is the standardized context in how we want SDKs to help users filter data. + - + -**Data collection and scrubbing:** The canonical spec for what data SDKs collect, default denylists (headers, cookies, query params), request body and cookie scrubbing, user-set data, and `beforeSend` is [Data Collection](/sdk/foundations/client/data-collection/). That spec supersedes the sensitive-data and cookie sections below for SDK behavior. This page retains **Structuring Data** and **Variable Size** and the legacy `send_default_pii` context for reference. +## Overview - +This spec defines which sensitive data the SDK removes and which sensitive data Relay removes. It also defines parameterization. Parameterization and scrubbing can use the same operations, but they have different purposes. -## Sensitive Data +The SDK knows where it collects a value, so it can remove a known-sensitive value before it sends it. Relay can parse payloads and apply content rules without adding work to the application. The rules below give each side the work that it can do best. -The normative rules for sensitive data, PII, cookies, request bodies, and user-set data are in [Data Collection](/sdk/foundations/client/data-collection/). The following is kept for context: +Related specs: -- SDKs collect rich debugging context — including user identity (`user.*`) and HTTP bodies — by default, while never sending credentials or secrets through automatic instrumentation. The legacy [_send-default-pii_](https://docs.sentry.io/platforms/python/configuration/options/#send-default-pii) toggle is replaced by the structured `dataCollection` configuration; user identity collection is controlled by `dataCollection.userInfo` (default `true`) and can be disabled to opt out (see [Data Collection](/sdk/foundations/client/data-collection/)). -- Certain sensitive data must never be sent through SDK instrumentation: header/cookie/query values matching the default denylist are replaced with `"[Filtered]"`. User-set data is always attached; only automatically gathered data is scrubbed. Users can use `beforeSend` / event processors to remove or redact any data. -- For the exact default denylist (partial, case-insensitive match), PII denylist (`x-forwarded-`, `-user`), cookies when unparsable, and raw request bodies, see [Data Collection — Default Denylist](/sdk/foundations/client/data-collection/#default-denylist) and [User-Set Data and Scrubbing](/sdk/foundations/client/data-collection/#user-set-data-scrubbing). -- For how `urlQueryParams` filtering applies to URL attributes, see [Data Collection — URLs](/sdk/foundations/client/data-collection/#urls). +- [Data Collection](/sdk/foundations/client/data-collection/) defines the `dataCollection` options, the sensitive denylist, and the rules for headers, cookies, URLs, and bodies. +- [Structuring Data](/sdk/telemetry/traces/structuring-data/) defines span name formats. +- [Queries Module](/sdk/telemetry/traces/modules/queries/#query-parameterization) defines how SDKs parameterize database queries. +- [Server-Side Data Scrubbing](https://docs.sentry.io/security-legal-pii/scrubbing/server-side-scrubbing/) describes the rules that Relay applies. -### Application State +## Concepts -App state can be critical to help developers reproduce bugs. For that reason, SDKs often collect app state and append to events through auto instrumentation. + -When attaching data that could potentially include sensitive data or PII, it's important to: +### Terms -- Add a note on the docs to notify developers. -- [Mark that part of the protocol on Relay](https://github.com/getsentry/relay/pull/1383) as such. This allows [data scrubbing](https://docs.sentry.io/product/relay/) to run on those fields. +- **Not collecting**: The SDK does not read the data. A `dataCollection` option controls this for each data category. +- **Parameterization**: The SDK replaces the variable parts of a value with placeholders, for example `SELECT * FROM users WHERE id = ?` or `/users/:id`. The result has low cardinality, so Sentry can group and search by it. +- **Scrubbing**: The SDK or Relay replaces a sensitive value with `"[Filtered]"`. The structure and the key names stay the same. -Some examples of auto instrumentation that could attach sensitive data: + -- A SQL integration that includes the query. If a user doesn't use parameterized queries, and appends sensitive data to it, the SDK could include that in the event payload. -- Desktop apps including window title. -- A Web framework routing instrumentation attaching route `to` and `from`. +## Behavior + + + +### The Purpose Decides the Category + +The purpose of an operation decides its category. The operation itself does not. + +For example, the SDK can parse a SQL query to replace its literals with `?`. The result is easier to group, so this is parameterization. If the SDK parses a request body to replace a password value, this is scrubbing. + + + + + +### Known-Sensitive Data in the SDK + +The SDK can identify some sensitive values at the collection point. A key name, a header, a cookie, a query parameter, or the source location tells the SDK that the value is sensitive. The SDK **MUST NOT** send these values. + +- The SDK **SHOULD** replace the value with `"[Filtered]"`. The key stays, so users can see that the data exists. +- The SDK **MAY** omit the item when no key or structure is left to keep. +- The SDK **MAY** split a value into key-value pairs when a standard grammar defines the pairs and the split costs about the same as reading the value. For example, the SDK can split a `Cookie` header on `;` and a query string on `&`. + +[Data Collection](/sdk/foundations/client/data-collection/#sensitive-denylist) defines the denylist and the rules for each data type. If a `dataCollection` option turns off a data category, the SDK does not collect that category. + + + + + +### Parameterization in the SDK + +- If the source supplies a parameterized form, the SDK **MUST** use it. Examples are the parameterized query of a database driver, the route template of a framework router, and the template of a log message. +- If the source does not supply a parameterized form, the SDK **MAY** parameterize the value when a known grammar defines it. The SDK can parse the value for this purpose. A module spec can make this a **SHOULD**, as the [Queries Module](/sdk/telemetry/traces/modules/queries/#query-parameterization) does for SQL. +- The SDK **MUST NOT** scrub a parameterized form. + + + + + +### Heuristic Scrubbing in Relay + +Relay scrubs sensitive data that only content rules can find, for example credit card numbers or bearer tokens. Relay also scrubs unstructured payloads, for example a request body or a database query. + +- The SDK **SHOULD NOT** parse a payload only to scrub it. +- The SDK **SHOULD NOT** apply content rules to find sensitive values. +- If [Sentry Conventions](https://getsentry.github.io/sentry-conventions/) defines an attribute for the data, the SDK **MUST** send the data in that attribute. +- An attribute that can contain sensitive data **MUST** have `apply_scrubbing` set to `auto` or `manual` in Sentry Conventions. See the [Sentry Conventions contribution guidelines](https://github.com/getsentry/sentry-conventions/blob/main/CONTRIBUTING.md). + +Relay applies its default rules to attributes with `apply_scrubbing` set to `auto`. Relay applies only the rules that target an attribute by name to attributes with `manual`. Relay does not scrub attributes with `never`. + +As of 2026-10-12, Relay does not parse payloads in span attributes. Relay applies its rules to the whole attribute value: + +- If the value contains a sensitive word, such as `password`, `secret`, or `auth`, Relay replaces the whole value with `"[Filtered]"`. +- Relay replaces other matches, such as credit card numbers, in place. +- Relay does not remove literals from `db.query.text`. Relay adds a parameterized copy in `sentry.normalized_db_query` for grouping. +- By default, Relay does not scrub email addresses or IP addresses. + + + + + +### Fields That Relay Cannot Scrub + +Relay does not scrub some fields, for example the span name and the metric name. These fields **MUST NOT** contain data that needs server-side scrubbing. For these fields, the SDK uses a parameterized form or a low-cardinality fallback. The [Queries Module](/sdk/telemetry/traces/modules/queries/#query-parameterization) defines the fallback for database spans. + +This rule does not cover the URL path in HTTP span names yet. [Structuring Data](/sdk/telemetry/traces/structuring-data/) defines that format. + + + + + +### User-Set Data + +The rules in this spec apply to data that the SDK collects automatically. [User-Set Data and Scrubbing](/sdk/foundations/client/data-collection/#user-set-data-scrubbing) defines how the SDK handles data that the user sets. + + + +## Changelog + + diff --git a/develop-docs/sdk/telemetry/metrics.mdx b/develop-docs/sdk/telemetry/metrics.mdx index 8907a754081737..a8b3d9c9a3408d 100644 --- a/develop-docs/sdk/telemetry/metrics.mdx +++ b/develop-docs/sdk/telemetry/metrics.mdx @@ -10,6 +10,9 @@ spec_depends_on: - id: sdk/foundations/state-management/scopes/attributes version: ">=1.0.0" spec_changelog: + - version: 3.2.0 + date: 2026-10-12 + summary: Guard user attributes with `dataCollection.userInfo` instead of `sendDefaultPii` - version: 3.1.0 date: 2026-10-08 summary: Listed client report discard reasons for metrics and clarified that the quantity is the number of discarded metrics @@ -152,7 +155,7 @@ SDKs **SHOULD** minimize the number of default attributes. Metrics cardinality c ### User Attributes -SDKs **MAY** attach user information as attributes, guarded by `sendDefaultPii` ([unless manually set by user](/sdk/foundations/data-scrubbing/#sensitive-data), since 2.5.0): +SDKs **MAY** attach user information as attributes, guarded by `dataCollection.userInfo` (or its predecessor `sendDefaultPii`) ([unless manually set by user](/sdk/foundations/client/data-collection/#user-set-data-scrubbing), since 2.5.0): 1. `user.id` — the user ID. Maps to `id` in the [User](/sdk/foundations/transport/event-payloads/user/) payload. 2. `user.name` — the username. Maps to `username` in the [User](/sdk/foundations/transport/event-payloads/user/) payload. diff --git a/develop-docs/sdk/telemetry/traces/modules/queries.mdx b/develop-docs/sdk/telemetry/traces/modules/queries.mdx index 838809be899e23..c50b7a0c534526 100644 --- a/develop-docs/sdk/telemetry/traces/modules/queries.mdx +++ b/develop-docs/sdk/telemetry/traces/modules/queries.mdx @@ -2,6 +2,12 @@ title: Queries Module --- + + This document uses key words such as "MUST", "SHOULD", and "MAY" as defined + in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) to indicate requirement + levels. + + The SDK should auto-instrument all database queries, and each query to the database should result in a span. This includes queries made manually, or via ORM. The Queries module supports SQL databases like PostgreSQL and MySQL, as well as MongoDB. It does not support other databases like Neo4j or ClickHouse. Regardless of that, the SDK should instrument database queries as fully and correctly as possible to ensure correct behavior and future compatibility. ## Span Attributes @@ -9,25 +15,39 @@ The SDK should auto-instrument all database queries, and each query to the datab | Attribute | Description | Notes | |:--|:--|:--| | `op` | Prefixed with `"db"` (e.g., `"db"`, `"db.query"`, `"db.sql.query"`) [^1] | Required | -| `description` | The full scrubbed query (e.g., `SELECT * FROM users where id = ?`) | Required, see [Query Scrubbing](#query-scrubbing) for details | +| `description` | The parameterized query (e.g., `SELECT * FROM users where id = ?`) | Required, see [Query Parameterization](#query-parameterization) for details | | `data` | A key-value mapping of span attributes. (e.g., `{"db.system": "postgresql", "db.name": "prod-2"}`) | Required for full experience. See [Span Data](#span-data) for details | -### Query Scrubbing +### Query Parameterization + +Parameterization replaces each literal value in a query with a placeholder, so Sentry can group the same query with different values. +See [Data Scrubbing](/sdk/foundations/data-scrubbing/#parameterization). -The query description should be scrubbed of any user-supplied values. +If the database driver supplies the parameterized query, the SDK **MUST** use it unchanged. Sentry supports the placeholders `?`, `%s`, `:c0` (e.g., `:c0`, `:c1`), and `$1` (e.g., `$1`, `$2`). -e.g., the query +If the driver does not supply a parameterized query, the SDK **SHOULD** replace all literals with `?`. For example, the query ```sql SELECT * FROM users WHERE id = 17; ``` -should be scrubbed to: + +becomes: ```sql SELECT * FROM users WHERE id = ?; ``` -The `?` parameter is a placeholder in the query. The SDK must scrub out all values and replace them with a placeholder. Supported placeholder values are `%s`, `?`, `:c0` (e.g., `:c0`, `:c1`) and `$1` (e.g., `$1`, `$2`). +If the SDK does not replace the literals, the span description **MUST NOT** contain the query. +The SDK uses the first available value of this list instead: + +1. `db.query.summary` +2. `{db.operation.name} {target}` +3. `{target}`, where the target is `db.collection.name`, `db.stored_procedure.name`, `db.namespace`, or `server.address` +4. `db.system.name` + +If the SDK does not replace the literals, the SDK **MAY** set `db.query.text` to the query as it is. Relay scrubs it (see [Heuristic Scrubbing in Relay](/sdk/foundations/data-scrubbing/#heuristic-scrubbing)). + +The SDK **SHOULD** set `db.query.summary` when the driver supplies it. The SDK **MAY** generate the summary from the parameterized query. The summary contains the operation and the target names, for example `SELECT users`. For MongoDB, the description should contain valid JSON. If replacing values with a placeholder, the string `"?"` should be used. @@ -66,7 +86,7 @@ This should result in the following span: ```json { - "description": "SELECT * FROM projects WHERE projects_user = 17", + "description": "SELECT * FROM projects WHERE projects_user = ?", "op": "db", "data": { "db.system": "postgresql", diff --git a/develop-docs/sdk/telemetry/traces/structuring-data.mdx b/develop-docs/sdk/telemetry/traces/structuring-data.mdx index 386c2519cd1aa5..4482af1bbf46e3 100644 --- a/develop-docs/sdk/telemetry/traces/structuring-data.mdx +++ b/develop-docs/sdk/telemetry/traces/structuring-data.mdx @@ -3,18 +3,16 @@ title: Structuring Data sidebar_order: 20 --- -For better data scrubbing on the server side, SDKs should save data in a structured way, when possible. Starting point of the discussion was [RFC-0038](https://github.com/getsentry/rfcs/blob/main/text/0038-scrubbing-sensitive-data.md) +SDKs store span data in a structured way, so that Relay can scrub it. [Data Scrubbing](/sdk/foundations/data-scrubbing/) defines which data the SDK scrubs and which data Relay scrubs. -See also: [Data Scrubbing](/sdk/foundations/data-scrubbing/) for general sensitive data handling requirements. +This page started with [RFC-0038](https://github.com/getsentry/rfcs/blob/main/text/0038-scrubbing-sensitive-data.md). The RFC uses `sendDefaultPii`, which [`dataCollection`](/sdk/foundations/client/data-collection/) replaces. ### Spans -This helps Relay to know what kind of data it receives and this helps with scrubbing sensitive data. - - `http` spans containing urls: The description of spans with `op` set to `http` must follow the format `HTTP_METHOD scheme://host/path` (ex. `GET https://example.com/foo`). - If an authority is present in the URL (`https://username:password@example.com`), the authority must be replaced with a placeholder regardless of `sendDefaultPii`, leading to a new URL of `https://[Filtered]:[Filtered]@example.com`. + If an authority is present in the URL (`https://username:password@example.com`), the authority must be replaced with a placeholder regardless of the `dataCollection` options, leading to a new URL of `https://[Filtered]:[Filtered]@example.com`. If query strings are present in the URL or fragments (Browser SDKs only) are present in the URI, both are set into the data attribute of the span. ```js @@ -33,8 +31,8 @@ This helps Relay to know what kind of data it receives and this helps with scrub - `db` spans containing database queries: (sql, graphql, elasticsearch, mongodb, ...) - The description of spans with `op` set to `db` must not include any query parameters. - Instead, use placeholders like `SELECT FROM 'users' WHERE id = ?` + The description of spans with `op` set to `db` must not contain literal values. Use the parameterized query, for example `SELECT * FROM users WHERE id = ?`. + See [Query Parameterization](/sdk/telemetry/traces/modules/queries/#query-parameterization) for the rules and the fallback. Additionally all semantic conventions of OpenTelemetry for database spans should be set in the `span.data` if applicable: https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/database/ From 8875a3c543c8814f9772057e3e7284a12633c46d Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Mon, 19 Oct 2026 15:02:06 +0200 Subject: [PATCH 2/2] review suggestions: server-side/client-side scrubbing --- .../client/data-collection/index.mdx | 8 ++-- .../sdk/foundations/data-scrubbing.mdx | 40 +++++++++---------- .../sdk/telemetry/traces/modules/queries.mdx | 2 +- .../sdk/telemetry/traces/structuring-data.mdx | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/develop-docs/sdk/foundations/client/data-collection/index.mdx b/develop-docs/sdk/foundations/client/data-collection/index.mdx index 2c599c28faffde..09b10f03d90fcf 100644 --- a/develop-docs/sdk/foundations/client/data-collection/index.mdx +++ b/develop-docs/sdk/foundations/client/data-collection/index.mdx @@ -10,7 +10,7 @@ spec_depends_on: spec_changelog: - version: 0.16.0 date: 2026-10-12 - summary: "Attach text bodies unchanged. SDKs no longer parse bodies to scrub them. Relay scrubs the body." + summary: "Attach text bodies unchanged. SDKs no longer parse bodies to scrub them. Server-side scrubbing applies to the body." - version: 0.15.0 date: 2026-09-29 summary: "Attach cookie headers as one string-array span attribute (`name=value` elements) instead of one attribute per cookie name. Filter nameless cookie segments and unparseable cookie strings." @@ -75,7 +75,7 @@ The new `dataCollection` configuration collects rich context for debugging by de Related specs: -- [Data Scrubbing](/sdk/foundations/data-scrubbing/) — which data the SDK scrubs, which data Relay scrubs, and parameterization +- [Data Scrubbing](/sdk/foundations/data-scrubbing/) — which data the SDK scrubs, which data server-side scrubbing removes, and parameterization - [Variable Size](/sdk/foundations/envelopes/event-payloads/#variable-size) — size limits for variable-size data - [Client](/sdk/foundations/client/) — client lifecycle and event pipeline - [Configuration](/sdk/foundations/client/configuration/) — top-level init options including `send_default_pii` (deprecated in favor of this spec) @@ -280,7 +280,7 @@ Unfiltered, raw cookie header values **MUST NOT** be sent. When in doubt, treat When bodies are collected via the `httpBodies` option (enabled by default; see [Body Type Collection](#body-type-collection)): -- **Text bodies:** SDKs **SHOULD** attach the body unchanged. SDKs **SHOULD NOT** parse the body to scrub it. Relay scrubs the body (see [Heuristic Scrubbing in Relay](/sdk/foundations/data-scrubbing/#heuristic-scrubbing)). +- **Text bodies:** SDKs **SHOULD** attach the body unchanged. SDKs **SHOULD NOT** parse the body to scrub it. Server-side scrubbing applies to the body (see [Server-Side Scrubbing](/sdk/foundations/data-scrubbing/#server-side-scrubbing)). - **Bodies that the framework already parsed:** SDKs **MAY** apply the denylist to the keys. Values for matching keys **MUST** be replaced with `"[Filtered]"`. No built-in option scrubs **keys**; users who need to hide header or cookie names **MUST** use `beforeSend` (or equivalent). @@ -540,7 +540,7 @@ SDKs **MUST** support configuring body collection for specific body types. The o Valid body type values: `"incomingRequest"`, `"outgoingRequest"`, `"incomingResponse"`, `"outgoingResponse"`. Body collection **MAY** not support allow/deny filtering. Unlike cookies or headers, body content has no predictable key structure for the SDK to filter at collection time. -The entire body is either collected or not. For how SDKs and Relay scrub a collected body, see [Request and Response Bodies](#request-and-response-bodies). Body data can still be redacted in `beforeSend` or event processors if needed. +The entire body is either collected or not. For how the SDK and server-side scrubbing handle a collected body, see [Request and Response Bodies](#request-and-response-bodies). Body data can still be redacted in `beforeSend` or event processors if needed. diff --git a/develop-docs/sdk/foundations/data-scrubbing.mdx b/develop-docs/sdk/foundations/data-scrubbing.mdx index 79affbf3a04d90..e2eca889d863f0 100644 --- a/develop-docs/sdk/foundations/data-scrubbing.mdx +++ b/develop-docs/sdk/foundations/data-scrubbing.mdx @@ -1,6 +1,6 @@ --- title: Data Scrubbing -description: Rules that decide which sensitive data the SDK removes, which sensitive data Relay removes, and how SDKs parameterize data. +description: Rules that decide which sensitive data the SDK scrubs, which sensitive data server-side scrubbing removes, and how SDKs parameterize data. spec_id: sdk/foundations/data-scrubbing spec_version: 1.0.0 spec_status: candidate @@ -10,7 +10,7 @@ spec_depends_on: spec_changelog: - version: 1.0.0 date: 2026-10-12 - summary: Initial spec. Define not collecting, parameterization, and scrubbing, and split the scrubbing work between SDKs and Relay. + summary: Initial spec. Define not collecting, parameterization, and scrubbing, and split the work between client-side and server-side scrubbing. sidebar_order: 6 --- @@ -20,16 +20,16 @@ sidebar_order: 6 ## Overview -This spec defines which sensitive data the SDK removes and which sensitive data Relay removes. It also defines parameterization. Parameterization and scrubbing can use the same operations, but they have different purposes. +This spec defines which sensitive data the SDK scrubs (client-side scrubbing) and which sensitive data Sentry scrubs after it receives the data (server-side scrubbing). It also defines parameterization. Parameterization and scrubbing can use the same operations, but they have different purposes. -The SDK knows where it collects a value, so it can remove a known-sensitive value before it sends it. Relay can parse payloads and apply content rules without adding work to the application. The rules below give each side the work that it can do best. +The SDK knows where it collects a value, so it can scrub a known-sensitive value before it sends it. Server-side scrubbing can parse payloads and apply content rules without adding work to the application. The rules below give each side the work that it can do best. Related specs: - [Data Collection](/sdk/foundations/client/data-collection/) defines the `dataCollection` options, the sensitive denylist, and the rules for headers, cookies, URLs, and bodies. - [Structuring Data](/sdk/telemetry/traces/structuring-data/) defines span name formats. - [Queries Module](/sdk/telemetry/traces/modules/queries/#query-parameterization) defines how SDKs parameterize database queries. -- [Server-Side Data Scrubbing](https://docs.sentry.io/security-legal-pii/scrubbing/server-side-scrubbing/) describes the rules that Relay applies. +- [Server-Side Data Scrubbing](https://docs.sentry.io/security-legal-pii/scrubbing/server-side-scrubbing/) describes the server-side rules and the settings that control them. ## Concepts @@ -39,7 +39,9 @@ Related specs: - **Not collecting**: The SDK does not read the data. A `dataCollection` option controls this for each data category. - **Parameterization**: The SDK replaces the variable parts of a value with placeholders, for example `SELECT * FROM users WHERE id = ?` or `/users/:id`. The result has low cardinality, so Sentry can group and search by it. -- **Scrubbing**: The SDK or Relay replaces a sensitive value with `"[Filtered]"`. The structure and the key names stay the same. +- **Scrubbing**: A sensitive value is replaced. The structure and the key names stay the same. The SDK uses `"[Filtered]"` as the replacement. The default server-side rules also use `"[Filtered]"`, but users can configure other replacements. +- **Client-side scrubbing**: The SDK scrubs the data before it sends the data. +- **Server-side scrubbing**: Sentry scrubs the data after it receives the data. The project and organization settings decide which rules apply. @@ -55,9 +57,9 @@ For example, the SDK can parse a SQL query to replace its literals with `?`. The - + -### Known-Sensitive Data in the SDK +### Client-Side Scrubbing The SDK can identify some sensitive values at the collection point. A key name, a header, a cookie, a query parameter, or the source location tells the SDK that the value is sensitive. The SDK **MUST NOT** send these values. @@ -79,33 +81,31 @@ The SDK can identify some sensitive values at the collection point. A key name, - + -### Heuristic Scrubbing in Relay +### Server-Side Scrubbing -Relay scrubs sensitive data that only content rules can find, for example credit card numbers or bearer tokens. Relay also scrubs unstructured payloads, for example a request body or a database query. +Server-side scrubbing finds sensitive data that only content rules can find, for example credit card numbers or bearer tokens. It also scrubs unstructured payloads, for example a request body or a database query. - The SDK **SHOULD NOT** parse a payload only to scrub it. - The SDK **SHOULD NOT** apply content rules to find sensitive values. +- If the data already has a structure, the SDK **SHOULD** keep the structure when it sends the data. For example, the SDK sends the key-value pairs that it already has, and not one string that contains all pairs. Server-side scrubbing and trimming then apply to each value. - If [Sentry Conventions](https://getsentry.github.io/sentry-conventions/) defines an attribute for the data, the SDK **MUST** send the data in that attribute. - An attribute that can contain sensitive data **MUST** have `apply_scrubbing` set to `auto` or `manual` in Sentry Conventions. See the [Sentry Conventions contribution guidelines](https://github.com/getsentry/sentry-conventions/blob/main/CONTRIBUTING.md). -Relay applies its default rules to attributes with `apply_scrubbing` set to `auto`. Relay applies only the rules that target an attribute by name to attributes with `manual`. Relay does not scrub attributes with `never`. +Server-side scrubbing applies the default rules to attributes with `apply_scrubbing` set to `auto`. It applies only the rules that target an attribute by name to attributes with `manual`. +It does not scrub attributes with `never`. -As of 2026-10-12, Relay does not parse payloads in span attributes. Relay applies its rules to the whole attribute value: - -- If the value contains a sensitive word, such as `password`, `secret`, or `auth`, Relay replaces the whole value with `"[Filtered]"`. -- Relay replaces other matches, such as credit card numbers, in place. -- Relay does not remove literals from `db.query.text`. Relay adds a parameterized copy in `sentry.normalized_db_query` for grouping. -- By default, Relay does not scrub email addresses or IP addresses. +As of 2026-10-12, server-side scrubbing does not parse payloads in span attributes, for example a cookie string or a JSON body. It applies its rules to the whole attribute value. +The project and organization settings decide which rules apply. See [Server-Side Data Scrubbing](https://docs.sentry.io/security-legal-pii/scrubbing/server-side-scrubbing/). -### Fields That Relay Cannot Scrub +### Fields Without Server-Side Scrubbing -Relay does not scrub some fields, for example the span name and the metric name. These fields **MUST NOT** contain data that needs server-side scrubbing. For these fields, the SDK uses a parameterized form or a low-cardinality fallback. The [Queries Module](/sdk/telemetry/traces/modules/queries/#query-parameterization) defines the fallback for database spans. +Server-side scrubbing does not apply to some fields, for example the span name and the metric name. These fields **MUST NOT** contain data that needs server-side scrubbing. For these fields, the SDK uses a parameterized form or a low-cardinality fallback. The [Queries Module](/sdk/telemetry/traces/modules/queries/#query-parameterization) defines the fallback for database spans. This rule does not cover the URL path in HTTP span names yet. [Structuring Data](/sdk/telemetry/traces/structuring-data/) defines that format. diff --git a/develop-docs/sdk/telemetry/traces/modules/queries.mdx b/develop-docs/sdk/telemetry/traces/modules/queries.mdx index c50b7a0c534526..fb51bada119948 100644 --- a/develop-docs/sdk/telemetry/traces/modules/queries.mdx +++ b/develop-docs/sdk/telemetry/traces/modules/queries.mdx @@ -45,7 +45,7 @@ The SDK uses the first available value of this list instead: 3. `{target}`, where the target is `db.collection.name`, `db.stored_procedure.name`, `db.namespace`, or `server.address` 4. `db.system.name` -If the SDK does not replace the literals, the SDK **MAY** set `db.query.text` to the query as it is. Relay scrubs it (see [Heuristic Scrubbing in Relay](/sdk/foundations/data-scrubbing/#heuristic-scrubbing)). +If the SDK does not replace the literals, the SDK **MAY** set `db.query.text` to the query as it is. Server-side scrubbing applies to it (see [Server-Side Scrubbing](/sdk/foundations/data-scrubbing/#server-side-scrubbing)). The SDK **SHOULD** set `db.query.summary` when the driver supplies it. The SDK **MAY** generate the summary from the parameterized query. The summary contains the operation and the target names, for example `SELECT users`. diff --git a/develop-docs/sdk/telemetry/traces/structuring-data.mdx b/develop-docs/sdk/telemetry/traces/structuring-data.mdx index 4482af1bbf46e3..9ab73d14409f1a 100644 --- a/develop-docs/sdk/telemetry/traces/structuring-data.mdx +++ b/develop-docs/sdk/telemetry/traces/structuring-data.mdx @@ -3,7 +3,7 @@ title: Structuring Data sidebar_order: 20 --- -SDKs store span data in a structured way, so that Relay can scrub it. [Data Scrubbing](/sdk/foundations/data-scrubbing/) defines which data the SDK scrubs and which data Relay scrubs. +SDKs store span data in a structured way, so that server-side scrubbing can scrub it. [Data Scrubbing](/sdk/foundations/data-scrubbing/) defines which data the SDK scrubs and which data server-side scrubbing removes. This page started with [RFC-0038](https://github.com/getsentry/rfcs/blob/main/text/0038-scrubbing-sensitive-data.md). The RFC uses `sendDefaultPii`, which [`dataCollection`](/sdk/foundations/client/data-collection/) replaces.