File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -104,4 +104,17 @@ describe('azureAnthropicProvider — SSRF pinning', () => {
104104 expect ( mockCreatePinnedFetch ) . not . toHaveBeenCalled ( )
105105 expect ( mockExecuteAnthropic ) . not . toHaveBeenCalled ( )
106106 } )
107+
108+ it ( 'fails closed when validation passes but yields no resolvable IP to pin' , async ( ) => {
109+ mockValidate . mockResolvedValue ( { isValid : true } )
110+
111+ await expect (
112+ azureAnthropicProvider . executeRequest (
113+ request ( { azureEndpoint : 'https://rebind.attacker.tld' } )
114+ )
115+ ) . rejects . toThrow ( 'could not resolve a pinnable IP address' )
116+
117+ expect ( mockCreatePinnedFetch ) . not . toHaveBeenCalled ( )
118+ expect ( mockExecuteAnthropic ) . not . toHaveBeenCalled ( )
119+ } )
107120} )
Original file line number Diff line number Diff line change @@ -38,9 +38,12 @@ export const azureAnthropicProvider: ProviderConfig = {
3838 } )
3939 throw new Error ( `Invalid Azure Anthropic endpoint: ${ validation . error } ` )
4040 }
41+ if ( ! validation . resolvedIP ) {
42+ throw new Error ( 'Invalid Azure Anthropic endpoint: could not resolve a pinnable IP address' )
43+ }
4144 // Pin the connection to the validated IP so the SDK's own DNS resolution at
4245 // connect time cannot be rebound to an internal address (TOCTOU SSRF).
43- pinnedFetch = createPinnedFetch ( validation . resolvedIP ! )
46+ pinnedFetch = createPinnedFetch ( validation . resolvedIP )
4447 }
4548
4649 const apiKey = request . apiKey
Original file line number Diff line number Diff line change @@ -138,6 +138,19 @@ describe('azureOpenAIProvider — SSRF pinning', () => {
138138 expect ( mockCreatePinnedFetch ) . not . toHaveBeenCalled ( )
139139 expect ( mockExecuteResponses ) . not . toHaveBeenCalled ( )
140140 } )
141+
142+ it ( 'fails closed when validation passes but yields no resolvable IP to pin' , async ( ) => {
143+ mockValidate . mockResolvedValue ( { isValid : true } )
144+
145+ await expect (
146+ azureOpenAIProvider . executeRequest (
147+ request ( { azureEndpoint : 'https://rebind.attacker.tld' } )
148+ )
149+ ) . rejects . toThrow ( 'could not resolve a pinnable IP address' )
150+
151+ expect ( mockCreatePinnedFetch ) . not . toHaveBeenCalled ( )
152+ expect ( mockExecuteResponses ) . not . toHaveBeenCalled ( )
153+ } )
141154 } )
142155
143156 describe ( 'Chat Completions path' , ( ) => {
Original file line number Diff line number Diff line change @@ -618,9 +618,12 @@ export const azureOpenAIProvider: ProviderConfig = {
618618 } )
619619 throw new Error ( `Invalid Azure OpenAI endpoint: ${ validation . error } ` )
620620 }
621+ if ( ! validation . resolvedIP ) {
622+ throw new Error ( 'Invalid Azure OpenAI endpoint: could not resolve a pinnable IP address' )
623+ }
621624 // Pin the connection to the validated IP so the SDK / fetch DNS resolution
622625 // at connect time cannot be rebound to an internal address (TOCTOU SSRF).
623- pinnedFetch = createPinnedFetch ( validation . resolvedIP ! )
626+ pinnedFetch = createPinnedFetch ( validation . resolvedIP )
624627 }
625628
626629 const apiKey = request . apiKey
You can’t perform that action at this time.
0 commit comments