@@ -78,6 +78,30 @@ export function ConcurrencyQueue ({ axios, config }) {
7878 this . running = [ ]
7979 this . paused = false
8080
81+ // SECURITY: Safe axios wrapper that always validates configs to prevent SSRF (CWE-918)
82+ // This ensures ALL axios requests are validated before execution
83+ const safeAxiosRequest = ( requestConfig ) => {
84+ // Validate and sanitize to prevent SSRF attacks (CWE-918)
85+ // This function throws an error if the URL is not allowed
86+ const sanitized = validateAndSanitizeConfig ( requestConfig )
87+
88+ // Additional runtime check: Ensure URL has been validated
89+ if ( ! sanitized || ! sanitized . url ) {
90+ throw new Error ( 'Invalid request: URL validation failed' )
91+ }
92+
93+ // SECURITY: The axios call below is safe because validateAndSanitizeConfig ensures:
94+ // 1. Only approved Contentstack domains are allowed
95+ // 2. Private IP addresses are blocked
96+ // 3. Only HTTP/HTTPS protocols are permitted
97+ // 4. URL injection attacks are prevented
98+ //
99+ // This axios call is protected by validateAndSanitizeConfig above which validates
100+ // all URLs against SSRF attacks. The function throws an error for any disallowed URLs.
101+ // deepcode ignore Ssrf: URL is validated and sanitized by validateAndSanitizeConfig before use
102+ return axios ( sanitized )
103+ }
104+
81105 // Helper function to determine if an error is a transient network failure
82106 const isTransientNetworkError = ( error ) => {
83107 // DNS resolution failures
@@ -166,15 +190,13 @@ export function ConcurrencyQueue ({ axios, config }) {
166190 setTimeout ( ( ) => {
167191 // Keep the request in running queue to maintain maxRequests constraint
168192 // Set retry flags to ensure proper queue handling
169- // SECURITY: Validate and sanitize request config to prevent SSRF (CWE-918)
170- // This ensures no malicious URLs from user input can be used
171- const sanitizedConfig = validateAndSanitizeConfig ( updateRequestConfig ( error , `Network retry ${ attempt } ` , delay ) )
172- sanitizedConfig . retryCount = sanitizedConfig . retryCount || 0
193+ const requestConfig = updateRequestConfig ( error , `Network retry ${ attempt } ` , delay )
194+ requestConfig . retryCount = requestConfig . retryCount || 0
173195
174196 // Use axios directly but ensure the running queue is properly managed
175197 // The request interceptor will handle this retry appropriately
176- // SECURITY: Using sanitizedConfig that has been validated against SSRF attacks
177- axios ( sanitizedConfig )
198+ // SECURITY: Using safeAxiosRequest wrapper that validates against SSRF attacks
199+ safeAxiosRequest ( requestConfig )
178200 . then ( ( response ) => {
179201 // On successful retry, call the original onComplete to properly clean up
180202 if ( error . config . onComplete ) {
@@ -326,11 +348,8 @@ export function ConcurrencyQueue ({ axios, config }) {
326348
327349 // Retry the requests that were pending due to token expiration
328350 this . running . forEach ( ( { request, resolve, reject } ) => {
329- // SECURITY: Validate and sanitize request config to prevent SSRF (CWE-918)
330- // This ensures no malicious URLs from user input can be used
331- const sanitizedConfig = validateAndSanitizeConfig ( request )
332- // SECURITY: Using sanitizedConfig that has been validated against SSRF attacks
333- axios ( sanitizedConfig ) . then ( resolve ) . catch ( reject )
351+ // SECURITY: Using safeAxiosRequest wrapper that validates against SSRF attacks
352+ safeAxiosRequest ( request ) . then ( resolve ) . catch ( reject )
334353 } )
335354 this . running = [ ] // Clear the running queue after retrying requests
336355 } catch ( error ) {
@@ -458,11 +477,8 @@ export function ConcurrencyQueue ({ axios, config }) {
458477 // Cool down the running requests
459478 delay ( wait , response . status === 401 )
460479 error . config . retryCount = networkError
461- // SECURITY: Validate and sanitize request config to prevent SSRF (CWE-918)
462- // This ensures no malicious URLs from user input can be used
463- const sanitizedConfig = validateAndSanitizeConfig ( updateRequestConfig ( error , retryErrorType , wait ) )
464- // SECURITY: Using sanitizedConfig that has been validated against SSRF attacks
465- return axios ( sanitizedConfig )
480+ // SECURITY: Using safeAxiosRequest wrapper that validates against SSRF attacks
481+ return safeAxiosRequest ( updateRequestConfig ( error , retryErrorType , wait ) )
466482 }
467483 if ( this . config . retryCondition && this . config . retryCondition ( error ) ) {
468484 retryErrorType = error . response ? `Error with status: ${ response . status } ` : `Error Code:${ error . code } `
@@ -492,11 +508,8 @@ export function ConcurrencyQueue ({ axios, config }) {
492508 error . config . retryCount = retryCount
493509 return new Promise ( function ( resolve ) {
494510 return setTimeout ( function ( ) {
495- // SECURITY: Validate and sanitize request config to prevent SSRF (CWE-918)
496- // This ensures no malicious URLs from user input can be used
497- const sanitizedConfig = validateAndSanitizeConfig ( updateRequestConfig ( error , retryErrorType , delaytime ) )
498- // SECURITY: Using sanitizedConfig that has been validated against SSRF attacks
499- return resolve ( axios ( sanitizedConfig ) )
511+ // SECURITY: Using safeAxiosRequest wrapper that validates against SSRF attacks
512+ return resolve ( safeAxiosRequest ( updateRequestConfig ( error , retryErrorType , delaytime ) ) )
500513 } , delaytime )
501514 } )
502515 }
0 commit comments