@@ -149,6 +149,44 @@ const SENSITIVE_HEADER_SNIPPETS = [
149149 'cookie' ,
150150] ;
151151
152+ /**
153+ * Extra substrings matched only against individual Cookie / Set-Cookie **names** (not header names),
154+ * so we can cover common session secrets that do not match {@link SENSITIVE_HEADER_SNIPPETS}
155+ * (e.g. `connect.sid` does not contain `session`) without false positives on arbitrary HTTP headers.
156+ *
157+ * Cookie names are checked with the same `includes()` list as headers plus these entries; omit redundant
158+ * cookie-only snippets that are already implied by a header match (e.g. `oauth` → `auth`, `id_token` → `token`,
159+ * `next-auth` → `auth`).
160+ */
161+ const SENSITIVE_COOKIE_NAME_SNIPPETS = [
162+ // Express / Connect default session cookie
163+ '.sid' ,
164+ // Opaque session ids (PHPSESSID, ASPSESSIONID*, BIGipServer*, *sessid*, …)
165+ 'sessid' ,
166+ // Laravel etc. "remember me" tokens
167+ 'remember' ,
168+ // OIDC / OAuth auxiliary (`oauth*` covered by header snippet `auth`)
169+ 'oidc' ,
170+ 'pkce' ,
171+ 'nonce' ,
172+ // RFC 6265bis high-security cookie name prefixes
173+ '__secure-' ,
174+ '__host-' ,
175+ // Load balancer / CDN sticky-session cookies (opaque routing tokens)
176+ 'awsalb' ,
177+ 'awselb' ,
178+ 'akamai' ,
179+ // BaaS / IdP session cookies (names often omit "session")
180+ '__stripe' ,
181+ 'cognito' ,
182+ 'firebase' ,
183+ 'supabase' ,
184+ 'sb-' ,
185+ // Step-up / MFA cookies
186+ 'mfa' ,
187+ '2fa' ,
188+ ] ;
189+
152190const PII_HEADER_SNIPPETS = [ 'x-forwarded-' , '-user' ] ;
153191
154192/**
@@ -196,17 +234,23 @@ export function httpHeadersToSpanAttributes(
196234
197235 const lowerCasedCookieKey = cookieKey . toLowerCase ( ) ;
198236
199- addSpanAttribute (
237+ addSpanAttribute ( {
200238 spanAttributes,
201- lowerCasedHeaderKey ,
202- lowerCasedCookieKey ,
203- cookieValue ,
239+ headerKey : lowerCasedHeaderKey ,
240+ cookieKey : lowerCasedCookieKey ,
241+ value : cookieValue ,
204242 sendDefaultPii,
205243 lifecycle,
206- ) ;
244+ } ) ;
207245 }
208246 } else {
209- addSpanAttribute ( spanAttributes , lowerCasedHeaderKey , '' , value , sendDefaultPii , lifecycle ) ;
247+ addSpanAttribute ( {
248+ spanAttributes,
249+ headerKey : lowerCasedHeaderKey ,
250+ value,
251+ sendDefaultPii,
252+ lifecycle,
253+ } ) ;
210254 }
211255 } ) ;
212256 } catch {
@@ -220,15 +264,31 @@ function normalizeAttributeKey(key: string): string {
220264 return key . replace ( / - / g, '_' ) ;
221265}
222266
223- function addSpanAttribute (
224- spanAttributes : Record < string , string > ,
225- headerKey : string ,
226- cookieKey : string ,
227- value : string | string [ ] | undefined ,
228- sendPii : boolean ,
229- lifecycle : 'request' | 'response' ,
230- ) : void {
231- const headerValue = handleHttpHeader ( cookieKey || headerKey , value , sendPii ) ;
267+ type AddSpanAttributeOptions = {
268+ spanAttributes : Record < string , string > ;
269+ /** Lowercased HTTP header name (e.g. `cookie`, `set-cookie`, `accept`). */
270+ headerKey : string ;
271+ /**
272+ * Lowercased cookie name when this attribute comes from a parsed `Cookie` / `Set-Cookie` value.
273+ * Omit for non-cookie headers; when present and non-empty, cookie-specific sensitivity rules apply.
274+ */
275+ cookieKey ?: string ;
276+ value : string | string [ ] | undefined ;
277+ sendDefaultPii : boolean ;
278+ lifecycle : 'request' | 'response' ;
279+ } ;
280+
281+ function addSpanAttribute ( {
282+ spanAttributes,
283+ headerKey,
284+ cookieKey,
285+ value,
286+ sendDefaultPii,
287+ lifecycle,
288+ } : AddSpanAttributeOptions ) : void {
289+ const isCookieSubKey = Boolean ( cookieKey ) ;
290+ const nameForSensitivity = cookieKey || headerKey ;
291+ const headerValue = handleHttpHeader ( nameForSensitivity , value , sendDefaultPii , isCookieSubKey ) ;
232292 if ( headerValue == null ) {
233293 return ;
234294 }
@@ -241,10 +301,15 @@ function handleHttpHeader(
241301 lowerCasedKey : string ,
242302 value : string | string [ ] | undefined ,
243303 sendPii : boolean ,
304+ isCookieSubKey : boolean = false ,
244305) : string | undefined {
306+ const snippetsForSensitivity = isCookieSubKey
307+ ? [ ...SENSITIVE_HEADER_SNIPPETS , ...SENSITIVE_COOKIE_NAME_SNIPPETS ]
308+ : SENSITIVE_HEADER_SNIPPETS ;
309+
245310 const isSensitive = sendPii
246- ? SENSITIVE_HEADER_SNIPPETS . some ( snippet => lowerCasedKey . includes ( snippet ) )
247- : [ ...PII_HEADER_SNIPPETS , ...SENSITIVE_HEADER_SNIPPETS ] . some ( snippet => lowerCasedKey . includes ( snippet ) ) ;
311+ ? snippetsForSensitivity . some ( snippet => lowerCasedKey . includes ( snippet ) )
312+ : [ ...PII_HEADER_SNIPPETS , ...snippetsForSensitivity ] . some ( snippet => lowerCasedKey . includes ( snippet ) ) ;
248313
249314 if ( isSensitive ) {
250315 return '[Filtered]' ;
0 commit comments