From 28a75d6fee73711c424fbc11bfd3a5753c1d86cc Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Wed, 4 Dec 2024 10:05:21 +0100 Subject: [PATCH] feat(core): Add `raw_security` envelope types --- packages/core/src/envelope.ts | 27 +++++++++++++++++++++++ packages/core/src/types-hoist/csp.ts | 15 +++++++++++++ packages/core/src/types-hoist/envelope.ts | 10 +++++++-- packages/core/src/types-hoist/index.ts | 3 +++ packages/core/src/utils-hoist/envelope.ts | 1 + 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 packages/core/src/types-hoist/csp.ts diff --git a/packages/core/src/envelope.ts b/packages/core/src/envelope.ts index 7281f2d2ea7f..999fb0681cf0 100644 --- a/packages/core/src/envelope.ts +++ b/packages/core/src/envelope.ts @@ -7,6 +7,9 @@ import type { Event, EventEnvelope, EventItem, + LegacyCSPReport, + RawSecurityEnvelope, + RawSecurityItem, SdkInfo, SdkMetadata, Session, @@ -24,6 +27,7 @@ import { createSpanEnvelopeItem, getSdkMetadataForEnvelopeHeader, } from './utils-hoist/envelope'; +import { uuid4 } from './utils-hoist/misc'; import { showSpanDropWarning, spanToJSON } from './utils/spanUtils'; /** @@ -141,3 +145,26 @@ export function createSpanEnvelope(spans: [SentrySpan, ...SentrySpan[]], client? return createEnvelope(headers, items); } + +/** + * Create an Envelope from a CSP report. + */ +export function createRawSecurityEnvelope( + report: LegacyCSPReport, + dsn: DsnComponents, + tunnel?: string, + release?: string, + environment?: string, +): RawSecurityEnvelope { + const envelopeHeaders = { + event_id: uuid4(), + ...(!!tunnel && dsn && { dsn: dsnToString(dsn) }), + }; + + const eventItem: RawSecurityItem = [ + { type: 'raw_security', sentry_release: release, sentry_environment: environment }, + report, + ]; + + return createEnvelope(envelopeHeaders, [eventItem]); +} diff --git a/packages/core/src/types-hoist/csp.ts b/packages/core/src/types-hoist/csp.ts new file mode 100644 index 000000000000..d1c49be6b858 --- /dev/null +++ b/packages/core/src/types-hoist/csp.ts @@ -0,0 +1,15 @@ +export interface LegacyCSPReport { + readonly 'csp-report': { + readonly 'document-uri'?: string; + readonly referrer?: string; + readonly 'blocked-uri'?: string; + readonly 'effective-directive'?: string; + readonly 'violated-directive'?: string; + readonly 'original-policy'?: string; + readonly disposition: 'enforce' | 'report' | 'reporting'; + readonly 'status-code'?: number; + readonly status?: string; + readonly 'script-sample'?: string; + readonly sample?: string; + }; +} diff --git a/packages/core/src/types-hoist/envelope.ts b/packages/core/src/types-hoist/envelope.ts index 20c67b8857fe..b5e2599942d4 100644 --- a/packages/core/src/types-hoist/envelope.ts +++ b/packages/core/src/types-hoist/envelope.ts @@ -1,6 +1,7 @@ import type { AttachmentType } from './attachment'; import type { SerializedCheckIn } from './checkin'; import type { ClientReport } from './clientreport'; +import type { LegacyCSPReport } from './csp'; import type { DsnComponents } from './dsn'; import type { Event } from './event'; import type { FeedbackEvent, UserFeedback } from './feedback'; @@ -41,7 +42,8 @@ export type EnvelopeItemType = | 'replay_recording' | 'check_in' | 'statsd' - | 'span'; + | 'span' + | 'raw_security'; export type BaseEnvelopeHeaders = { [key: string]: unknown; @@ -84,6 +86,7 @@ type ProfileItemHeaders = { type: 'profile' }; type ProfileChunkItemHeaders = { type: 'profile_chunk' }; type StatsdItemHeaders = { type: 'statsd'; length: number }; type SpanItemHeaders = { type: 'span' }; +type RawSecurityHeaders = { type: 'raw_security'; sentry_release?: string; sentry_environment?: string }; export type EventItem = BaseEnvelopeItem; export type AttachmentItem = BaseEnvelopeItem; @@ -100,6 +103,7 @@ export type FeedbackItem = BaseEnvelopeItem; export type ProfileItem = BaseEnvelopeItem; export type ProfileChunkItem = BaseEnvelopeItem; export type SpanItem = BaseEnvelopeItem>; +export type RawSecurityItem = BaseEnvelopeItem; export type EventEnvelopeHeaders = { event_id: string; sent_at: string; trace?: Partial }; type SessionEnvelopeHeaders = { sent_at: string }; @@ -120,6 +124,7 @@ export type CheckInEnvelope = BaseEnvelope; export type StatsdEnvelope = BaseEnvelope; export type SpanEnvelope = BaseEnvelope; export type ProfileChunkEnvelope = BaseEnvelope; +export type RawSecurityEnvelope = BaseEnvelope; export type Envelope = | EventEnvelope @@ -129,6 +134,7 @@ export type Envelope = | ReplayEnvelope | CheckInEnvelope | StatsdEnvelope - | SpanEnvelope; + | SpanEnvelope + | RawSecurityEnvelope; export type EnvelopeItem = Envelope[1][number]; diff --git a/packages/core/src/types-hoist/index.ts b/packages/core/src/types-hoist/index.ts index 5dd1839aeba7..2e0976a4f482 100644 --- a/packages/core/src/types-hoist/index.ts +++ b/packages/core/src/types-hoist/index.ts @@ -43,6 +43,8 @@ export type { UserFeedbackItem, CheckInItem, CheckInEnvelope, + RawSecurityEnvelope, + RawSecurityItem, StatsdItem, StatsdEnvelope, ProfileItem, @@ -179,3 +181,4 @@ export type { export type { ParameterizedString } from './parameterize'; export type { ContinuousProfiler, ProfilingIntegration, Profiler } from './profiling'; export type { ViewHierarchyData, ViewHierarchyWindow } from './view-hierarchy'; +export type { LegacyCSPReport } from './csp'; diff --git a/packages/core/src/utils-hoist/envelope.ts b/packages/core/src/utils-hoist/envelope.ts index 5014d6fe130d..be640b90ad4f 100644 --- a/packages/core/src/utils-hoist/envelope.ts +++ b/packages/core/src/utils-hoist/envelope.ts @@ -224,6 +224,7 @@ const ITEM_TYPE_TO_DATA_CATEGORY_MAP: Record = { feedback: 'feedback', span: 'span', statsd: 'metric_bucket', + raw_security: 'security', }; /**