Skip to content

Commit fc83a7d

Browse files
fix: Properly sanitize the event context and SDK info (#1943)
We now properly sanitize the event context and SDK info, fixing the problem where using a `Date` in the context dictionary caused serialization issues and the context to be removed completely.
1 parent 8ae9ab1 commit fc83a7d

File tree

6 files changed

+33
-121
lines changed

6 files changed

+33
-121
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- Properly sanitize the event context and SDK information (#1943)
8+
39
## 7.20.0
410

511
### Features

Sources/Sentry/SentryEnvelope.m

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -101,49 +101,23 @@ - (instancetype)initWithEvent:(SentryEvent *)event
101101
NSData *json = [SentrySerialization dataWithJSONObject:[event serialize] error:&error];
102102

103103
if (nil != error) {
104-
// It could be the user added something to the context or the sdk that can't serialized.
105-
event.context = nil;
106-
event.sdk = nil;
107-
error = nil;
108-
[SentrySerialization dataWithJSONObject:[event serialize] error:&error];
109-
110-
// The context or the sdk was the problem for serialization. Add a breadcrumb that we are
111-
// dropping the context and the sdk.
112-
if (nil == error) {
113-
NSMutableArray<SentryBreadcrumb *> *breadcrumbs = [event.breadcrumbs mutableCopy];
114-
if (nil == breadcrumbs) {
115-
breadcrumbs = [[NSMutableArray alloc] init];
116-
}
117-
118-
SentryBreadcrumb *crumb = [[SentryBreadcrumb alloc] initWithLevel:kSentryLevelError
119-
category:@"sentry.event"];
120-
crumb.message = @"A value set to the context or sdk is not serializable. Dropping "
121-
@"context and sdk.";
122-
crumb.type = @"error";
123-
[breadcrumbs addObject:crumb];
124-
event.breadcrumbs = breadcrumbs;
125-
126-
json = [SentrySerialization dataWithJSONObject:[event serialize] error:nil];
127-
} else {
128-
// We don't know what caused the serialization to fail.
129-
SentryEvent *errorEvent = [[SentryEvent alloc] initWithLevel:kSentryLevelWarning];
130-
131-
// Add some context to the event. We can only set simple properties otherwise we
132-
// risk that the conversion fails again.
133-
NSString *message =
134-
[NSString stringWithFormat:@"JSON conversion error for event with message: '%@'",
135-
event.message];
136-
137-
errorEvent.message = [[SentryMessage alloc] initWithFormatted:message];
138-
errorEvent.releaseName = event.releaseName;
139-
errorEvent.environment = event.environment;
140-
errorEvent.platform = event.platform;
141-
errorEvent.timestamp = event.timestamp;
142-
143-
// We accept the risk that this simple serialization fails. Therefore we ignore the
144-
// error on purpose.
145-
json = [SentrySerialization dataWithJSONObject:[errorEvent serialize] error:nil];
146-
}
104+
// We don't know what caused the serialization to fail.
105+
SentryEvent *errorEvent = [[SentryEvent alloc] initWithLevel:kSentryLevelWarning];
106+
107+
// Add some context to the event. We can only set simple properties otherwise we
108+
// risk that the conversion fails again.
109+
NSString *message = [NSString
110+
stringWithFormat:@"JSON conversion error for event with message: '%@'", event.message];
111+
112+
errorEvent.message = [[SentryMessage alloc] initWithFormatted:message];
113+
errorEvent.releaseName = event.releaseName;
114+
errorEvent.environment = event.environment;
115+
errorEvent.platform = event.platform;
116+
errorEvent.timestamp = event.timestamp;
117+
118+
// We accept the risk that this simple serialization fails. Therefore we ignore the
119+
// error on purpose.
120+
json = [SentrySerialization dataWithJSONObject:[errorEvent serialize] error:nil];
147121
}
148122

149123
// event.type can be nil and the server infers error if there's a stack trace, otherwise

Sources/Sentry/SentryEvent.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ - (void)addThreads:(NSMutableDictionary *)serializedData
118118

119119
- (void)addSimpleProperties:(NSMutableDictionary *)serializedData
120120
{
121-
[serializedData setValue:self.sdk forKey:@"sdk"];
121+
[serializedData setValue:[self.sdk sentry_sanitize] forKey:@"sdk"];
122122
[serializedData setValue:self.releaseName forKey:@"release"];
123123
[serializedData setValue:self.dist forKey:@"dist"];
124124
[serializedData setValue:self.environment forKey:@"environment"];
@@ -138,7 +138,7 @@ - (void)addSimpleProperties:(NSMutableDictionary *)serializedData
138138

139139
[serializedData setValue:[self serializeBreadcrumbs] forKey:@"breadcrumbs"];
140140

141-
[serializedData setValue:self.context forKey:@"contexts"];
141+
[serializedData setValue:[self.context sentry_sanitize] forKey:@"contexts"];
142142

143143
if (nil != self.message) {
144144
[serializedData setValue:[self.message serialize] forKey:@"message"];

Tests/SentryTests/Protocol/SentryEnvelopeTests.swift

Lines changed: 3 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -36,37 +36,18 @@ class SentryEnvelopeTests: XCTestCase {
3636
event.message = SentryMessage(formatted: "Don't do this")
3737
event.releaseName = "releaseName1.0.0"
3838
event.environment = "save the environment"
39-
event.sdk = ["version": sdkVersion]
40-
return event
41-
}
42-
43-
var eventWithFaultyContext: Event {
44-
let event = self.event
45-
event.context = ["dont": ["dothis": Date()]]
46-
return event
47-
}
48-
49-
var eventWithFaultySDK: Event {
50-
let event = self.event
51-
event.sdk = ["dont": ["dothis": Date()]]
52-
return event
53-
}
54-
55-
var eventWithFaultyContextAndBreadrumb: Event {
56-
let event = eventWithFaultyContext
57-
event.breadcrumbs = [breadcrumb]
39+
event.sdk = ["version": sdkVersion, "date": Date()]
5840
return event
5941
}
6042

6143
var eventWithContinousSerializationFailure: Event {
62-
let event = EventSerilazationFailure()
44+
let event = EventSerializationFailure()
6345
event.message = SentryMessage(formatted: "Failure")
6446
event.releaseName = "release"
6547
event.environment = "environment"
6648
event.platform = "platform"
6749
return event
6850
}
69-
7051
}
7152

7253
private let fixture = Fixture()
@@ -204,49 +185,6 @@ class SentryEnvelopeTests: XCTestCase {
204185
XCTAssertEqual(expected, actual)
205186
}
206187

207-
func testInitWithEvent_FaultyContextNoBreadcrumbs_SendsEventWithBreadcrumb() {
208-
let event = fixture.eventWithFaultyContext
209-
let envelope = SentryEnvelope(event: event)
210-
211-
XCTAssertEqual(1, envelope.items.count)
212-
XCTAssertNotNil(envelope.items.first?.data)
213-
if let data = envelope.items.first?.data {
214-
let json = String(data: data, encoding: .utf8) ?? ""
215-
assertContainsBreadcrumbForDroppingContextAndSDK(json)
216-
assertEventDoesNotContainContext(json)
217-
}
218-
}
219-
220-
func testInitWithEvent_FaultySDKNoBreadcrumbs_SendsEventWithBreadcrumb() {
221-
let event = fixture.eventWithFaultySDK
222-
let envelope = SentryEnvelope(event: event)
223-
224-
XCTAssertEqual(1, envelope.items.count)
225-
XCTAssertNotNil(envelope.items.first?.data)
226-
if let data = envelope.items.first?.data {
227-
let json = String(data: data, encoding: .utf8) ?? ""
228-
assertContainsBreadcrumbForDroppingContextAndSDK(json)
229-
assertEventDoesNotContainContext(json)
230-
}
231-
}
232-
233-
func testInitWithEvent_FaultyContextAndBreadcrumb_SendsEventWithBreadcrumbs() {
234-
let event = fixture.eventWithFaultyContextAndBreadrumb
235-
236-
let envelope = SentryEnvelope(event: event)
237-
238-
XCTAssertEqual(1, envelope.items.count)
239-
XCTAssertNotNil(envelope.items.first?.data)
240-
if let data = envelope.items.first?.data {
241-
let json = String(data: data, encoding: .utf8) ?? ""
242-
243-
assertContainsBreadcrumbForDroppingContextAndSDK(json)
244-
assertEventDoesNotContainContext(json)
245-
246-
json.assertContains(fixture.breadcrumb.message!, "breadrumb message")
247-
}
248-
}
249-
250188
func testInitWithEvent_SerializationFails_SendsEventWithSerializationFailure() {
251189
let event = fixture.eventWithContinousSerializationFailure
252190
let envelope = SentryEnvelope(event: event)
@@ -348,19 +286,11 @@ class SentryEnvelopeTests: XCTestCase {
348286
}
349287
}
350288

351-
private func assertContainsBreadcrumbForDroppingContextAndSDK(_ json: String) {
352-
json.assertContains("A value set to the context or sdk is not serializable. Dropping context and sdk.", "breadcrumb message")
353-
354-
json.assertContains("\"category\":\"sentry.event\"", "breadcrumb category")
355-
json.assertContains("\"type\":\"error\"", "breadcrumb type")
356-
json.assertContains("\"level\":\"error\"", "breadcrumb level")
357-
}
358-
359289
private func assertEventDoesNotContainContext(_ json: String) {
360290
XCTAssertFalse(json.contains("\"contexts\":{"))
361291
}
362292

363-
private class EventSerilazationFailure: Event {
293+
private class EventSerializationFailure: Event {
364294
override func serialize() -> [String: Any] {
365295
return ["is going": ["to fail": Date()]]
366296
}

Tests/SentryTests/Protocol/SentryEventTests.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ class SentryEventTests: XCTestCase {
4747
XCTAssertEqual(1, crumbs?.count)
4848

4949
let context = actual["contexts"] as? [String: [String: Any]]
50-
XCTAssertEqual(1, context?.count)
51-
XCTAssertEqual(TestData.context["context"], context?["context"] as? [String: String])
50+
XCTAssertEqual(context?.count, 1)
51+
XCTAssertEqual(context?["context"]?.count, 2)
52+
XCTAssertEqual(context?["context"]?["c"] as! String, "a")
53+
XCTAssertEqual(context?["context"]?["date"] as! String, "1970-01-01T00:00:10.000Z")
5254

5355
XCTAssertNotNil(actual["message"] as? [String: Any])
5456

Tests/SentryTests/Protocol/TestData.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class TestData {
1212
}
1313
}
1414
static let sdk = ["name": SentryMeta.sdkName, "version": SentryMeta.versionString]
15-
static let context = ["context": ["c": "a"]]
15+
static let context = ["context": ["c": "a", "date": timestamp]]
1616

1717
static var crumb: Breadcrumb {
1818
let crumb = Breadcrumb()

0 commit comments

Comments
 (0)