Skip to content

Commit 4336914

Browse files
authored
Merge pull request #411 from contentstack/fix/dev
snyk issue fix
2 parents 60d11dd + 97b0321 commit 4336914

File tree

1 file changed

+49
-6
lines changed

1 file changed

+49
-6
lines changed

lib/core/Util.js

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,10 @@ const isValidURL = (url) => {
140140
} catch (error) {
141141
// If URL parsing fails, it might be a relative URL without protocol
142142
// Allow it if it doesn't contain protocol indicators or suspicious patterns
143-
return !url.includes('://') && !url.includes('\\') && !url.includes('@')
143+
if (error instanceof TypeError) {
144+
return !url.includes('://') && !url.includes('\\') && !url.includes('@')
145+
}
146+
return false
144147
}
145148
}
146149

@@ -149,6 +152,7 @@ const isAllowedHost = (hostname) => {
149152
const allowedDomains = [
150153
'api.contentstack.io',
151154
'eu-api.contentstack.com',
155+
'au-api.contentstack.com',
152156
'azure-na-api.contentstack.com',
153157
'azure-eu-api.contentstack.com',
154158
'gcp-na-api.contentstack.com',
@@ -177,14 +181,53 @@ const isAllowedHost = (hostname) => {
177181
})
178182
}
179183

184+
// Helper function to validate individual URL properties
185+
const validateURLProperty = (config, prop) => {
186+
if (config[prop] && !isValidURL(config[prop])) {
187+
throw new Error(`SSRF Prevention: ${prop} "${config[prop]}" is not allowed`)
188+
}
189+
}
190+
191+
// Helper function to validate combined URL (baseURL + url)
192+
const validateCombinedURL = (baseURL, url) => {
193+
try {
194+
let fullURL
195+
// Handle relative URLs with baseURL
196+
if (url.startsWith('/') || url.startsWith('./') || url.startsWith('../')) {
197+
fullURL = new URL(url, baseURL).href
198+
} else {
199+
// If url is absolute, it overrides baseURL
200+
fullURL = url
201+
}
202+
203+
if (!isValidURL(fullURL)) {
204+
throw new Error(`SSRF Prevention: Combined URL "${fullURL}" is not allowed`)
205+
}
206+
} catch (error) {
207+
if (error.message.startsWith('SSRF Prevention:')) {
208+
throw error
209+
}
210+
throw new Error(`SSRF Prevention: Invalid URL combination of baseURL "${baseURL}" and url "${url}"`)
211+
}
212+
}
213+
180214
export const validateAndSanitizeConfig = (config) => {
181-
if (!config || !config.url) {
182-
throw new Error('Invalid request configuration: missing URL')
215+
if (!config) {
216+
throw new Error('Invalid request configuration: missing config')
217+
}
218+
219+
// Validate all possible URL properties in axios config to prevent SSRF attacks
220+
const urlProperties = ['url', 'baseURL']
221+
urlProperties.forEach(prop => validateURLProperty(config, prop))
222+
223+
// If we have both baseURL and url, validate the combined URL
224+
if (config.baseURL && config.url) {
225+
validateCombinedURL(config.baseURL, config.url)
183226
}
184227

185-
// Validate the URL to prevent SSRF attacks
186-
if (!isValidURL(config.url)) {
187-
throw new Error(`SSRF Prevention: URL "${config.url}" is not allowed`)
228+
// Ensure we have at least one URL property
229+
if (!config.url && !config.baseURL) {
230+
throw new Error('Invalid request configuration: missing URL or baseURL')
188231
}
189232

190233
return config

0 commit comments

Comments
 (0)