feat(scrubbing): adopt denylist defined by Data Collection spec - #1198
feat(scrubbing): adopt denylist defined by Data Collection spec#1198solnic wants to merge 1 commit into
Conversation
502b842 to
b569ac0
Compare
ad98de1 to
052b357
Compare
052b357 to
4005705
Compare
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.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4005705. Configure here.
4005705 to
9925981
Compare
| `Sentry.Scrubber.default_header_keys/0` and the `:header_scrubber` | ||
| option of `Sentry.PlugContext`. | ||
|
|
||
| *Available since 14.0.0*. |
There was a problem hiding this comment.
Are we gonna have breaking changes because of this, since we're bumping the major version?
| which is the denylist required by the | ||
| [Sentry Data Collection spec](https://develop.sentry.dev/sdk/foundations/client/data-collection/). | ||
| The spec defines custom deny-mode terms as additive, so there is no way | ||
| to shrink the default list — that is deliberate. |
There was a problem hiding this comment.
Generally em-dashes are not spaces (en dashes are). Sadly agents love to space around em dashes
| to shrink the default list — that is deliberate. | |
| to shrink the default list—that is deliberate. |
| Terms are matched as case-insensitive substrings of the key name, so | ||
| `"ref"` redacts `"internal_ref"` and `"REF_ID"` alike. | ||
|
|
||
| This does not affect header scrubbing, which uses its own list — see |
9925981 to
6b41dab
Compare
| defp configured_param_keys, | ||
| do: @default_scrubbed_param_keys ++ Sentry.Config.scrubber()[:param_keys] |
There was a problem hiding this comment.
Bug: Sentry.Config.scrubber() returns [] by default. Accessing [:param_keys] on it returns nil, causing an ArgumentError when concatenated with @default_scrubbed_param_keys.
Severity: CRITICAL
Suggested Fix
Ensure that the return value of Sentry.Config.scrubber() is handled safely before key access. Instead of directly accessing keys like config[:param_keys], use Keyword.get(config, :param_keys, []) to provide a default empty list. This will prevent the ArgumentError when concatenating with nil if the key is not present.
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: lib/sentry/scrubber.ex#L398-L399
Potential issue: When the `:scrubber` option is not configured,
`Sentry.Config.scrubber()` returns its default value, an empty list `[]`. The function
`configured_param_keys` then attempts to access `[:param_keys]` on this empty list,
which results in `nil`. This `nil` value is then used in a list concatenation operation
(`@default_scrubbed_param_keys ++ nil`), which raises an `ArgumentError`. This crash
occurs during request handling for any application that has not explicitly configured
the `:scrubber` option, which is the default scenario for most users. A similar issue
exists in `configured_private_allow_list` which accesses `[:conn_private_allow_list]` on
the same empty list.
Also affects:
lib/sentry/scrubber.ex:402~403
Did we get this right? 👍 / 👎 to inform future reviews.

Now the default sensitive keys are the denylist the Data Collection spec requires, matched as a case-insensitive substring, and
config :sentry, scrubber: [param_keys: [...]]extends that list with your own terms.Before
internal_refis the row to focus on. Relay does not recognise that name, so it is the one value the panel shows exactly as the SDK left it — and there is no way to make the SDK redact it, because the:param_keysoption does not exist yet:internal_ref—cfgref-20260909-082441-before, in both Body and Query Stringtoken,api_key— not in the old denylistPASSWORD— the same term aspassword, missed because matching was case-sensitiveuser_password— the same term again, missed because matching required exact equalityAfter
Every one of those is redacted, each by a different rule:
internal_ref—*********, sensitive only because the app configuredscrubber: [param_keys: ["internal_ref"]]token— a key the spec denylist addsapi_key— matched as a substring ofkeyPASSWORD— matched toouser_password— matched as a substring