@@ -692,6 +692,61 @@ describe('InstrumentationPatchTest', () => {
692692 } ) ;
693693 } ) ;
694694
695+ it ( 'Prevents recursion when credentials provider makes STS calls' , async ( ) => {
696+ // Track credentials provider calls and skip flag state
697+ let credentialsProviderCallCount = 0 ;
698+ let skipCredentialCaptureValue = false ;
699+
700+ // Mock span for attribute capture
701+ const mockSpan = { setAttribute : sinon . stub ( ) } ;
702+ sinon . stub ( trace , 'getSpan' ) . returns ( mockSpan as unknown as Span ) ;
703+
704+ // Mock OpenTelemetry context to track skip-credential-capture flag
705+ const mockContext = {
706+ getValue : ( key : symbol ) =>
707+ key . toString ( ) . includes ( 'skip-credential-capture' ) ? skipCredentialCaptureValue : undefined ,
708+ setValue : ( key : symbol , value : any ) => {
709+ if ( key . toString ( ) . includes ( 'skip-credential-capture' ) ) skipCredentialCaptureValue = value ;
710+ return mockContext ;
711+ } ,
712+ deleteValue : ( ) => mockContext ,
713+ } ;
714+ sinon . stub ( context , 'active' ) . returns ( mockContext ) ;
715+
716+ // Capture middleware added to stack
717+ const middlewareStack : any [ ] = [ ] ;
718+ const recursiveSdkSend = extractAwsSdkInstrumentation ( PATCHED_INSTRUMENTATIONS )
719+ [ '_getV3SmithyClientSendPatch' ] ( ( ) => Promise . resolve ( ) )
720+ . bind ( {
721+ middlewareStack : { add : ( middleware : any , config : any ) => middlewareStack . push ( [ middleware , config ] ) } ,
722+ config : {
723+ // Credentials provider that recursively calls SDK (simulates STS)
724+ credentials : async ( ) => {
725+ credentialsProviderCallCount ++ ;
726+ await recursiveSdkSend ( { } , null ) ;
727+ return { accessKeyId : 'test-access-key' } ;
728+ } ,
729+ region : ( ) => Promise . resolve ( 'us-west-2' ) ,
730+ } ,
731+ } ) ;
732+
733+ // Initial SDK call triggers middleware setup
734+ await recursiveSdkSend ( { } , null ) ;
735+ expect ( skipCredentialCaptureValue ) . toBe ( false ) ;
736+
737+ // Execute credentials extraction middleware
738+ await middlewareStack [ 1 ] [ 0 ] ( ( ) => Promise . resolve ( ) , null ) ( { } ) ;
739+
740+ // Verify recursion prevention: only one credentials call despite recursive setup
741+ expect ( credentialsProviderCallCount ) . toBe ( 1 ) ;
742+ expect ( skipCredentialCaptureValue ) . toBe ( true ) ;
743+ expect (
744+ mockSpan . setAttribute . calledWith ( AWS_ATTRIBUTE_KEYS . AWS_AUTH_ACCOUNT_ACCESS_KEY , 'test-access-key' )
745+ ) . toBeTruthy ( ) ;
746+
747+ sinon . restore ( ) ;
748+ } ) ;
749+
695750 it ( 'injects trace context header into request via propagator' , async ( ) => {
696751 lambda = new Lambda ( {
697752 region : region ,
0 commit comments