@@ -3,6 +3,7 @@ import crypto from 'node:crypto';
33import fs from 'node:fs' ;
44import os from 'node:os' ;
55import path from 'node:path' ;
6+ import { redactDiagnosticData } from './redaction.ts' ;
67
78type DiagnosticLevel = 'info' | 'warn' | 'error' | 'debug' ;
89
@@ -33,11 +34,6 @@ type DiagnosticsScope = DiagnosticsScopeOptions & {
3334
3435const diagnosticsStorage = new AsyncLocalStorage < DiagnosticsScope > ( ) ;
3536
36- const SENSITIVE_KEY_RE =
37- / ( t o k e n | s e c r e t | p a s s w o r d | a u t h o r i z a t i o n | c o o k i e | a p i [ _ - ] ? k e y | a c c e s s [ _ - ] ? k e y | p r i v a t e [ _ - ] ? k e y ) / i;
38- const SENSITIVE_VALUE_RE =
39- / ( b e a r e r \s + [ a - z 0 - 9 . _ - ] + | (?: a p i [ _ - ] ? k e y | t o k e n | s e c r e t | p a s s w o r d ) \s * [ = : ] \s * \S + ) / i;
40-
4137export function createRequestId ( ) : string {
4238 return crypto . randomBytes ( 8 ) . toString ( 'hex' ) ;
4339}
@@ -161,58 +157,6 @@ export function flushDiagnosticsToSessionFile(options: { force?: boolean } = {})
161157 }
162158}
163159
164- export function redactDiagnosticData < T > ( input : T ) : T {
165- return redactValue ( input , new WeakSet < object > ( ) ) as T ;
166- }
167-
168- function redactValue ( value : unknown , seen : WeakSet < object > , keyHint ?: string ) : unknown {
169- if ( value === null || value === undefined ) return value ;
170- if ( typeof value === 'string' ) return redactString ( value , keyHint ) ;
171- if ( typeof value !== 'object' ) return value ;
172-
173- if ( seen . has ( value as object ) ) return '[Circular]' ;
174- seen . add ( value as object ) ;
175-
176- if ( Array . isArray ( value ) ) {
177- return value . map ( ( entry ) => redactValue ( entry , seen ) ) ;
178- }
179-
180- const output : Record < string , unknown > = { } ;
181- for ( const [ key , entry ] of Object . entries ( value as Record < string , unknown > ) ) {
182- if ( SENSITIVE_KEY_RE . test ( key ) ) {
183- output [ key ] = '[REDACTED]' ;
184- continue ;
185- }
186- output [ key ] = redactValue ( entry , seen , key ) ;
187- }
188- return output ;
189- }
190-
191- function redactString ( value : string , keyHint ?: string ) : string {
192- const trimmed = value . trim ( ) ;
193- if ( ! trimmed ) return value ;
194- if ( keyHint && SENSITIVE_KEY_RE . test ( keyHint ) ) return '[REDACTED]' ;
195- if ( SENSITIVE_VALUE_RE . test ( trimmed ) ) return '[REDACTED]' ;
196- const maskedUrl = redactUrl ( trimmed ) ;
197- if ( maskedUrl ) return maskedUrl ;
198- if ( trimmed . length > 400 ) return `${ trimmed . slice ( 0 , 200 ) } ...<truncated>` ;
199- return trimmed ;
200- }
201-
202- function redactUrl ( value : string ) : string | null {
203- try {
204- const parsed = new URL ( value ) ;
205- if ( parsed . search ) parsed . search = '?REDACTED' ;
206- if ( parsed . username || parsed . password ) {
207- parsed . username = 'REDACTED' ;
208- parsed . password = 'REDACTED' ;
209- }
210- return parsed . toString ( ) ;
211- } catch {
212- return null ;
213- }
214- }
215-
216160function sanitizePathPart ( value : string ) : string {
217161 return value . replace ( / [ ^ a - z A - Z 0 - 9 . _ - ] / g, '_' ) ;
218162}
0 commit comments