Skip to content

Commit f40fd24

Browse files
authored
fix(otlp-transformer): add check for possible unsafe json parse (#6588)
1 parent 394eeb0 commit f40fd24

7 files changed

Lines changed: 75 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
1717

1818
### :rocket: Features
1919

20-
* feat(sdk-logs): implement log creation metrics [#6433](https://github.com/open-telemetry/opentelemetry-js/pull/6433) @anuraaga
20+
* feat(sdk-logs): implement log creation metrics [#6433](https://github.com/open-telemetry/opentelemetry-js/pull/6433) @anuraaga
2121

2222
### :bug: Bug Fixes
2323

24-
fix(opentelemetry-resources): do not discard OTEL_RESOURCE_ATTRIBUTES when it contains empty kv pairs
24+
* fix(opentelemetry-resources): do not discard OTEL_RESOURCE_ATTRIBUTES when it contains empty kv pairs
25+
* fix(otlp-transformer): add check for possible unsafe json parse [#6588](https://github.com/open-telemetry/opentelemetry-js/pull/6588) @maryliag
2526

2627
### :books: Documentation
2728

experimental/packages/otlp-transformer/src/logs/json/logs.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { ReadableLogRecord } from '@opentelemetry/sdk-logs';
77
import { createExportLogsServiceRequest } from '../internal';
88
import type { IExportLogsServiceResponse } from '../export-response';
99
import { JSON_ENCODER } from '../../common/utils';
10+
import { diag } from '@opentelemetry/api';
1011

1112
/*
1213
* @experimental this serializer may receive breaking changes in minor versions, pin this package's version when using this constant
@@ -25,6 +26,13 @@ export const JsonLogsSerializer: ISerializer<
2526
return {};
2627
}
2728
const decoder = new TextDecoder();
28-
return JSON.parse(decoder.decode(arg)) as IExportLogsServiceResponse;
29+
try {
30+
return JSON.parse(decoder.decode(arg)) as IExportLogsServiceResponse;
31+
} catch (err) {
32+
diag.warn(
33+
`Failed to parse logs export response: ${err.message}. Returning empty response`
34+
);
35+
return {};
36+
}
2937
},
3038
};

experimental/packages/otlp-transformer/src/metrics/json/metrics.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { ResourceMetrics } from '@opentelemetry/sdk-metrics';
77
import { createExportMetricsServiceRequest } from '../internal';
88
import type { IExportMetricsServiceResponse } from '../export-response';
99
import { JSON_ENCODER } from '../../common/utils';
10+
import { diag } from '@opentelemetry/api';
1011

1112
export const JsonMetricsSerializer: ISerializer<
1213
ResourceMetrics,
@@ -22,6 +23,13 @@ export const JsonMetricsSerializer: ISerializer<
2223
return {};
2324
}
2425
const decoder = new TextDecoder();
25-
return JSON.parse(decoder.decode(arg)) as IExportMetricsServiceResponse;
26+
try {
27+
return JSON.parse(decoder.decode(arg)) as IExportMetricsServiceResponse;
28+
} catch (err) {
29+
diag.warn(
30+
`Failed to parse metrics export response: ${err.message}. Returning empty response`
31+
);
32+
return {};
33+
}
2634
},
2735
};

experimental/packages/otlp-transformer/src/trace/json/trace.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { ReadableSpan } from '@opentelemetry/sdk-trace-base';
77
import type { IExportTraceServiceResponse } from '../export-response';
88
import { createExportTraceServiceRequest } from '../internal';
99
import { JSON_ENCODER } from '../../common/utils';
10+
import { diag } from '@opentelemetry/api';
1011

1112
export const JsonTraceSerializer: ISerializer<
1213
ReadableSpan[],
@@ -22,6 +23,13 @@ export const JsonTraceSerializer: ISerializer<
2223
return {};
2324
}
2425
const decoder = new TextDecoder();
25-
return JSON.parse(decoder.decode(arg)) as IExportTraceServiceResponse;
26+
try {
27+
return JSON.parse(decoder.decode(arg)) as IExportTraceServiceResponse;
28+
} catch (err) {
29+
diag.warn(
30+
`Failed to parse trace export response: ${err.message}. Returning empty response`
31+
);
32+
return {};
33+
}
2634
},
2735
};

experimental/packages/otlp-transformer/test/logs.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,21 @@ describe('Logs', () => {
503503
);
504504
});
505505

506+
it('deserializes a malformed response', () => {
507+
const malformedResponse =
508+
'{ "partialSuccess": { "errorMessage": foo, "rejectedLogRecords": 1, }';
509+
const encoder = new TextEncoder();
510+
const encodedResponse = encoder.encode(malformedResponse);
511+
const deserializedResponse =
512+
JsonLogsSerializer.deserializeResponse(encodedResponse);
513+
514+
assert.deepEqual(
515+
deserializedResponse,
516+
{},
517+
'Malformed response should result in an empty object being returned'
518+
);
519+
});
520+
506521
it('does not throw when deserializing an empty response', () => {
507522
assert.doesNotThrow(() =>
508523
JsonLogsSerializer.deserializeResponse(new Uint8Array([]))

experimental/packages/otlp-transformer/test/metrics.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,21 @@ describe('Metrics', () => {
984984
);
985985
});
986986

987+
it('deserializes a malformed response', () => {
988+
const malformedResponse =
989+
'{ "partialSuccess": { "errorMessage": foo, "rejectedLogRecords": 1, }';
990+
const encoder = new TextEncoder();
991+
const encodedResponse = encoder.encode(malformedResponse);
992+
const deserializedResponse =
993+
JsonMetricsSerializer.deserializeResponse(encodedResponse);
994+
995+
assert.deepEqual(
996+
deserializedResponse,
997+
{},
998+
'Malformed response should result in an empty object being returned'
999+
);
1000+
});
1001+
9871002
it('does not throw when deserializing an empty response', () => {
9881003
assert.doesNotThrow(() =>
9891004
JsonMetricsSerializer.deserializeResponse(new Uint8Array([]))

experimental/packages/otlp-transformer/test/trace.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,21 @@ describe('Trace', () => {
586586
);
587587
});
588588

589+
it('deserializes a malformed response', () => {
590+
const malformedResponse =
591+
'{ "partialSuccess": { "errorMessage": foo, "rejectedLogRecords": 1, }';
592+
const encoder = new TextEncoder();
593+
const encodedResponse = encoder.encode(malformedResponse);
594+
const deserializedResponse =
595+
JsonTraceSerializer.deserializeResponse(encodedResponse);
596+
597+
assert.deepEqual(
598+
deserializedResponse,
599+
{},
600+
'Malformed response should result in an empty object being returned'
601+
);
602+
});
603+
589604
it('does not throw when deserializing an empty response', () => {
590605
assert.doesNotThrow(() =>
591606
JsonTraceSerializer.deserializeResponse(new Uint8Array([]))

0 commit comments

Comments
 (0)