Skip to content

Commit afc3e14

Browse files
committed
feat: add safe url check for preview endpoint in request handling
1 parent 50e763c commit afc3e14

1 file changed

Lines changed: 23 additions & 2 deletions

File tree

src/lib/request.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,27 @@ function buildFullUrl(baseURL: string | undefined, url: string, queryString: str
2525
return `${base}${url}?${queryString}`;
2626
}
2727

28+
/**
29+
* Safely checks if a URL points to the preview endpoint by parsing the hostname
30+
* This prevents substring matching vulnerabilities (e.g., evil.com/rest-preview.contentstack.com)
31+
*/
32+
function isPreviewEndpoint(url: string): boolean {
33+
try {
34+
// Ensure URL has a protocol for proper parsing
35+
let urlToParse = url;
36+
if (!url.startsWith('http://') && !url.startsWith('https://')) {
37+
urlToParse = `https://${url}`;
38+
}
39+
40+
const parsedUrl = new URL(urlToParse);
41+
// Check hostname exactly, not as substring
42+
return parsedUrl.hostname === 'rest-preview.contentstack.com';
43+
} catch {
44+
// If URL parsing fails, default to false for safety
45+
return false;
46+
}
47+
}
48+
2849
/**
2950
* Makes the HTTP request with proper URL handling
3051
*/
@@ -36,8 +57,8 @@ async function makeRequest(
3657
): Promise<any> {
3758
// Determine URL length threshold based on whether it's a preview endpoint
3859
// rest-preview.contentstack.com has stricter limits, so use lower threshold
39-
const isPreviewEndpoint = actualFullUrl.includes('rest-preview.contentstack.com');
40-
const urlLengthThreshold = isPreviewEndpoint ? 1500 : 2000;
60+
const isPreview = isPreviewEndpoint(actualFullUrl);
61+
const urlLengthThreshold = isPreview ? 1500 : 2000;
4162

4263
// If URL is too long, use direct axios request with full URL
4364
if (actualFullUrl.length > urlLengthThreshold) {

0 commit comments

Comments
 (0)