diff --git a/CHANGELOG.md b/CHANGELOG.md index 65c079f4085..894ac24d453 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,17 @@ ## Unreleased -**Internal**: - -- No longer writes Spans as trace items. ([#5152](https://github.com/getsentry/relay/pull/5152)) - **Features**: +- Enables more PII rules for AI attributes. ([#5166](https://github.com/getsentry/relay/pull/5166) - Add Memory Info context to event schema. ([#5154](https://github.com/getsentry/relay/pull/5154)) - Add Thread Pool Info context to event schema. ([#5153](https://github.com/getsentry/relay/pull/5153)) - Add Unity Info context to event schema. ([#5155](https://github.com/getsentry/relay/pull/5155)) +**Internal**: + +- No longer writes Spans as trace items. ([#5152](https://github.com/getsentry/relay/pull/5152)) + ## 25.9.0 **Breaking Changes**: diff --git a/relay-pii/src/convert.rs b/relay-pii/src/convert.rs index 2bf5ad33111..df10617fc41 100644 --- a/relay-pii/src/convert.rs +++ b/relay-pii/src/convert.rs @@ -58,6 +58,40 @@ static SENSITIVE_COOKIES: Lazy = Lazy::new(|| { .unwrap() }); +/// Certain fields in payloads are very important to the product and ideally are not destroyed by +/// PII scrubbing. Our default scrubber is very aggressive and includes fully destructive rules. +/// To still have some PII scrubbing applied, this manual override exists and injects replace only +/// PII rules to these fields. +/// +/// This is currently a workaround until we have a more powerful version of the PII processor +/// in place: . +static REPLACE_ONLY_SELECTOR: Lazy = Lazy::new(|| { + [ + "$logentry.formatted", + "$span.data.'gen_ai.prompt'", + "attributes.'gen_ai.prompt'.value", + "$span.data.'gen_ai.request.messages'", + "attributes.'gen_ai.request.messages'.value", + "$span.data.'gen_ai.tool.input'", + "attributes.'gen_ai.tool.input'.value", + "$span.data.'gen_ai.tool.output'", + "attributes.'gen_ai.tool.output'.value", + "$span.data.'gen_ai.response.tool_calls'", + "attributes.'gen_ai.response.tool_calls'.value", + "$span.data.'gen_ai.response.text'", + "attributes.'gen_ai.response.text'.value", + "$span.data.'gen_ai.response.object'", + "attributes.'gen_ai.response.object'.value", + "$span.data.'gen_ai.request.available_tools'", + "attributes.'gen_ai.request.available_tools'.value", + "$span.data.'gen_ai.tool.name'", + "attributes.'gen_ai.tool.name'.value", + ] + .join("|") + .parse() + .unwrap() +}); + pub fn to_pii_config( datascrubbing_config: &DataScrubbingConfig, ) -> Result, PiiConfigError> { @@ -72,14 +106,8 @@ pub fn to_pii_config( vec!["@anything:filter".to_owned()], ); - let logentry_selector: SelectorSpec = SelectorSpec::Path(vec![ - SelectorPathItem::Type(ValueType::LogEntry), - SelectorPathItem::Key("formatted".to_owned()), - ]); - - // Apply smart scrubbing rules only to logentry.formatted applications.insert( - logentry_selector, + REPLACE_ONLY_SELECTOR.clone(), vec![ "@email:replace".to_owned(), "@creditcard:replace".to_owned(), @@ -190,7 +218,7 @@ pub fn to_pii_config( #[cfg(test)] mod tests { use relay_event_schema::processor::{ProcessingState, process_value}; - use relay_event_schema::protocol::Event; + use relay_event_schema::protocol::{Event, SpanV2}; use relay_protocol::{FromValue, assert_annotated_snapshot}; use similar_asserts::assert_eq; @@ -309,15 +337,15 @@ THd+9FBxiHLGXNKhG/FRSyREXEt+NyYIf/0cyByc9tNksat794ddUqnLOg0vwSkv "$http.env.REMOTE_ADDR || $user.ip_address || $sdk.client_ip || $span.sentry_tags.'user.ip'": [ "@anything:remove" ], - "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ - "@anything:filter" - ], - "$logentry.formatted": [ + "$logentry.formatted || $span.data.'gen_ai.prompt' || attributes.'gen_ai.prompt'.value || $span.data.'gen_ai.request.messages' || attributes.'gen_ai.request.messages'.value || $span.data.'gen_ai.tool.input' || attributes.'gen_ai.tool.input'.value || $span.data.'gen_ai.tool.output' || attributes.'gen_ai.tool.output'.value || $span.data.'gen_ai.response.tool_calls' || attributes.'gen_ai.response.tool_calls'.value || $span.data.'gen_ai.response.text' || attributes.'gen_ai.response.text'.value || $span.data.'gen_ai.response.object' || attributes.'gen_ai.response.object'.value || $span.data.'gen_ai.request.available_tools' || attributes.'gen_ai.request.available_tools'.value || $span.data.'gen_ai.tool.name' || attributes.'gen_ai.tool.name'.value": [ "@email:replace", "@creditcard:replace", "@iban:replace", "@usssn:replace", "@bearer:replace" + ], + "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ + "@anything:filter" ] } } @@ -341,15 +369,15 @@ THd+9FBxiHLGXNKhG/FRSyREXEt+NyYIf/0cyByc9tNksat794ddUqnLOg0vwSkv "$http.env.REMOTE_ADDR || $user.ip_address || $sdk.client_ip || $span.sentry_tags.'user.ip'": [ "@anything:remove" ], - "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ - "@anything:filter" - ], - "$logentry.formatted": [ + "$logentry.formatted || $span.data.'gen_ai.prompt' || attributes.'gen_ai.prompt'.value || $span.data.'gen_ai.request.messages' || attributes.'gen_ai.request.messages'.value || $span.data.'gen_ai.tool.input' || attributes.'gen_ai.tool.input'.value || $span.data.'gen_ai.tool.output' || attributes.'gen_ai.tool.output'.value || $span.data.'gen_ai.response.tool_calls' || attributes.'gen_ai.response.tool_calls'.value || $span.data.'gen_ai.response.text' || attributes.'gen_ai.response.text'.value || $span.data.'gen_ai.response.object' || attributes.'gen_ai.response.object'.value || $span.data.'gen_ai.request.available_tools' || attributes.'gen_ai.request.available_tools'.value || $span.data.'gen_ai.tool.name' || attributes.'gen_ai.tool.name'.value": [ "@email:replace", "@creditcard:replace", "@iban:replace", "@usssn:replace", "@bearer:replace" + ], + "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ + "@anything:filter" ] } } @@ -384,15 +412,15 @@ THd+9FBxiHLGXNKhG/FRSyREXEt+NyYIf/0cyByc9tNksat794ddUqnLOg0vwSkv "$http.env.REMOTE_ADDR || $user.ip_address || $sdk.client_ip || $span.sentry_tags.'user.ip'": [ "@anything:remove" ], - "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ - "@anything:filter" - ], - "$logentry.formatted": [ + "$logentry.formatted || $span.data.'gen_ai.prompt' || attributes.'gen_ai.prompt'.value || $span.data.'gen_ai.request.messages' || attributes.'gen_ai.request.messages'.value || $span.data.'gen_ai.tool.input' || attributes.'gen_ai.tool.input'.value || $span.data.'gen_ai.tool.output' || attributes.'gen_ai.tool.output'.value || $span.data.'gen_ai.response.tool_calls' || attributes.'gen_ai.response.tool_calls'.value || $span.data.'gen_ai.response.text' || attributes.'gen_ai.response.text'.value || $span.data.'gen_ai.response.object' || attributes.'gen_ai.response.object'.value || $span.data.'gen_ai.request.available_tools' || attributes.'gen_ai.request.available_tools'.value || $span.data.'gen_ai.tool.name' || attributes.'gen_ai.tool.name'.value": [ "@email:replace", "@creditcard:replace", "@iban:replace", "@usssn:replace", "@bearer:replace" + ], + "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ + "@anything:filter" ] } } @@ -416,15 +444,15 @@ THd+9FBxiHLGXNKhG/FRSyREXEt+NyYIf/0cyByc9tNksat794ddUqnLOg0vwSkv "$http.env.REMOTE_ADDR || $user.ip_address || $sdk.client_ip || $span.sentry_tags.'user.ip'": [ "@anything:remove" ], - "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ - "@anything:filter" - ], - "$logentry.formatted": [ + "$logentry.formatted || $span.data.'gen_ai.prompt' || attributes.'gen_ai.prompt'.value || $span.data.'gen_ai.request.messages' || attributes.'gen_ai.request.messages'.value || $span.data.'gen_ai.tool.input' || attributes.'gen_ai.tool.input'.value || $span.data.'gen_ai.tool.output' || attributes.'gen_ai.tool.output'.value || $span.data.'gen_ai.response.tool_calls' || attributes.'gen_ai.response.tool_calls'.value || $span.data.'gen_ai.response.text' || attributes.'gen_ai.response.text'.value || $span.data.'gen_ai.response.object' || attributes.'gen_ai.response.object'.value || $span.data.'gen_ai.request.available_tools' || attributes.'gen_ai.request.available_tools'.value || $span.data.'gen_ai.tool.name' || attributes.'gen_ai.tool.name'.value": [ "@email:replace", "@creditcard:replace", "@iban:replace", "@usssn:replace", "@bearer:replace" + ], + "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ + "@anything:filter" ] } } @@ -1337,15 +1365,15 @@ THd+9FBxiHLGXNKhG/FRSyREXEt+NyYIf/0cyByc9tNksat794ddUqnLOg0vwSkv "$http.env.REMOTE_ADDR || $user.ip_address || $sdk.client_ip || $span.sentry_tags.'user.ip'": [ "@anything:remove" ], - "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ - "@anything:filter" - ], - "$logentry.formatted": [ + "$logentry.formatted || $span.data.'gen_ai.prompt' || attributes.'gen_ai.prompt'.value || $span.data.'gen_ai.request.messages' || attributes.'gen_ai.request.messages'.value || $span.data.'gen_ai.tool.input' || attributes.'gen_ai.tool.input'.value || $span.data.'gen_ai.tool.output' || attributes.'gen_ai.tool.output'.value || $span.data.'gen_ai.response.tool_calls' || attributes.'gen_ai.response.tool_calls'.value || $span.data.'gen_ai.response.text' || attributes.'gen_ai.response.text'.value || $span.data.'gen_ai.response.object' || attributes.'gen_ai.response.object'.value || $span.data.'gen_ai.request.available_tools' || attributes.'gen_ai.request.available_tools'.value || $span.data.'gen_ai.tool.name' || attributes.'gen_ai.tool.name'.value": [ "@email:replace", "@creditcard:replace", "@iban:replace", "@usssn:replace", "@bearer:replace" + ], + "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ + "@anything:filter" ] } } @@ -1803,4 +1831,98 @@ THd+9FBxiHLGXNKhG/FRSyREXEt+NyYIf/0cyByc9tNksat794ddUqnLOg0vwSkv process_value(&mut data, &mut pii_processor, ProcessingState::root()).unwrap(); assert_annotated_snapshot!(data); } + + #[test] + fn test_replace_fields_applies_to_span_data() { + let mut data = Event::from_value( + serde_json::json!({ + "spans": [{ + "data": { + "gen_ai.prompt": "Buy me a drink with my creditcard 4111-1111-1111-1111", + } + }] + }) + .into(), + ); + + let pii_config = to_pii_config(&simple_enabled_config()).unwrap(); + let mut pii_processor = PiiProcessor::new(pii_config.compiled()); + process_value(&mut data, &mut pii_processor, ProcessingState::root()).unwrap(); + assert_annotated_snapshot!(data, @r#" + { + "spans": [ + { + "data": { + "gen_ai.prompt": "Buy me a drink with my creditcard [creditcard]" + } + } + ], + "_meta": { + "spans": { + "0": { + "data": { + "gen_ai.prompt": { + "": { + "rem": [ + [ + "@creditcard:replace", + "s", + 34, + 46 + ] + ], + "len": 53 + } + } + } + } + } + } + } + "#); + } + + #[test] + fn test_replace_fields_applies_to_attributes() { + let mut data = SpanV2::from_value( + serde_json::json!({ + "attributes": { + "gen_ai.prompt": {"value": "Buy me a drink with my creditcard 4111-1111-1111-1111"}, + } + }) + .into(), + ); + + let pii_config = to_pii_config(&simple_enabled_config()).unwrap(); + let mut pii_processor = PiiProcessor::new(pii_config.compiled()); + process_value(&mut data, &mut pii_processor, ProcessingState::root()).unwrap(); + assert_annotated_snapshot!(data, @r#" + { + "attributes": { + "gen_ai.prompt": { + "value": "Buy me a drink with my creditcard [creditcard]" + } + }, + "_meta": { + "attributes": { + "gen_ai.prompt": { + "value": { + "": { + "rem": [ + [ + "@creditcard:replace", + "s", + 34, + 46 + ] + ], + "len": 53 + } + } + } + } + } + } + "#); + } } diff --git a/relay-pii/src/snapshots/relay_pii__convert__tests__regression_more_odd_keys.snap b/relay-pii/src/snapshots/relay_pii__convert__tests__regression_more_odd_keys.snap index bf8bb66192c..acee54fe14e 100644 --- a/relay-pii/src/snapshots/relay_pii__convert__tests__regression_more_odd_keys.snap +++ b/relay-pii/src/snapshots/relay_pii__convert__tests__regression_more_odd_keys.snap @@ -11,15 +11,15 @@ expression: pii_config "$http.env.REMOTE_ADDR || $user.ip_address || $sdk.client_ip || $span.sentry_tags.'user.ip'": [ "@anything:remove" ], - "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ - "@anything:filter" - ], - "$logentry.formatted": [ + "$logentry.formatted || $span.data.'gen_ai.prompt' || attributes.'gen_ai.prompt'.value || $span.data.'gen_ai.request.messages' || attributes.'gen_ai.request.messages'.value || $span.data.'gen_ai.tool.input' || attributes.'gen_ai.tool.input'.value || $span.data.'gen_ai.tool.output' || attributes.'gen_ai.tool.output'.value || $span.data.'gen_ai.response.tool_calls' || attributes.'gen_ai.response.tool_calls'.value || $span.data.'gen_ai.response.text' || attributes.'gen_ai.response.text'.value || $span.data.'gen_ai.response.object' || attributes.'gen_ai.response.object'.value || $span.data.'gen_ai.request.available_tools' || attributes.'gen_ai.request.available_tools'.value || $span.data.'gen_ai.tool.name' || attributes.'gen_ai.tool.name'.value": [ "@email:replace", "@creditcard:replace", "@iban:replace", "@usssn:replace", "@bearer:replace" + ], + "*.cookies.sentrysid || *.cookies.sudo || *.cookies.su || *.cookies.session || *.cookies.__session || *.cookies.sessionid || *.cookies.user_session || *.cookies.symfony || *.cookies.phpsessid || *.cookies.fasthttpsessionid || *.cookies.mysession || *.cookies.irissessionid || *.cookies.csrf || *.cookies.xsrf || *.cookies._xsrf || *.cookies._csrf || *.cookies.csrf-token || *.cookies.csrf_token || *.cookies.xsrf-token || *.cookies.xsrf_token || *.cookies.fastcsrf || *.cookies._iris_csrf": [ + "@anything:filter" ] } }