@@ -2,9 +2,11 @@ import { randomBytes } from "node:crypto";
22
33const TRACEPARENT_VERSION = "00" ;
44const DEFAULT_TRACE_FLAGS = "01" ;
5+ const MAX_TRACEPARENT_LENGTH = 128 ;
56const TRACE_ID_RE = / ^ [ 0 - 9 a - f ] { 32 } $ / ;
67const SPAN_ID_RE = / ^ [ 0 - 9 a - f ] { 16 } $ / ;
78const TRACE_FLAGS_RE = / ^ [ 0 - 9 a - f ] { 2 } $ / ;
9+ const TRACEPARENT_VERSION_RE = / ^ [ 0 - 9 a - f ] { 2 } $ / ;
810
911export type DiagnosticTraceContext = {
1012 /** W3C trace id, 32 lowercase hex chars. */
@@ -29,6 +31,22 @@ function isNonZeroHex(value: string): boolean {
2931 return ! / ^ 0 + $ / . test ( value ) ;
3032}
3133
34+ function randomTraceId ( ) : string {
35+ let traceId = randomHex ( 16 ) ;
36+ while ( ! isNonZeroHex ( traceId ) ) {
37+ traceId = randomHex ( 16 ) ;
38+ }
39+ return traceId ;
40+ }
41+
42+ function randomSpanId ( ) : string {
43+ let spanId = randomHex ( 8 ) ;
44+ while ( ! isNonZeroHex ( spanId ) ) {
45+ spanId = randomHex ( 8 ) ;
46+ }
47+ return spanId ;
48+ }
49+
3250export function isValidDiagnosticTraceId ( value : unknown ) : value is string {
3351 return typeof value === "string" && TRACE_ID_RE . test ( value ) && isNonZeroHex ( value ) ;
3452}
@@ -68,12 +86,19 @@ function normalizeTraceFlags(value: unknown): string | undefined {
6886export function parseDiagnosticTraceparent (
6987 traceparent : string | undefined ,
7088) : DiagnosticTraceContext | undefined {
71- const parts = traceparent ?. trim ( ) . toLowerCase ( ) . split ( "-" ) ;
72- if ( ! parts || parts . length !== 4 ) {
89+ if ( typeof traceparent !== "string" || traceparent . length > MAX_TRACEPARENT_LENGTH ) {
90+ return undefined ;
91+ }
92+ const parts = traceparent . trim ( ) . toLowerCase ( ) . split ( "-" ) ;
93+ if ( ! parts || parts . length < 4 ) {
7394 return undefined ;
7495 }
7596 const [ version , traceId , spanId , traceFlags ] = parts ;
76- if ( version !== TRACEPARENT_VERSION ) {
97+ if (
98+ ! TRACEPARENT_VERSION_RE . test ( version ) ||
99+ version === "ff" ||
100+ ( version === TRACEPARENT_VERSION && parts . length !== 4 )
101+ ) {
77102 return undefined ;
78103 }
79104 const normalizedTraceId = normalizeTraceId ( traceId ) ;
@@ -108,8 +133,8 @@ export function createDiagnosticTraceContext(
108133 input : DiagnosticTraceContextInput = { } ,
109134) : DiagnosticTraceContext {
110135 const parsed = parseDiagnosticTraceparent ( input . traceparent ) ;
111- const traceId = normalizeTraceId ( input . traceId ) ?? parsed ?. traceId ?? randomHex ( 16 ) ;
112- const spanId = normalizeSpanId ( input . spanId ) ?? parsed ?. spanId ?? randomHex ( 8 ) ;
136+ const traceId = normalizeTraceId ( input . traceId ) ?? parsed ?. traceId ?? randomTraceId ( ) ;
137+ const spanId = normalizeSpanId ( input . spanId ) ?? parsed ?. spanId ?? randomSpanId ( ) ;
113138 const parentSpanId = normalizeSpanId ( input . parentSpanId ) ;
114139 return {
115140 traceId,
0 commit comments