Skip to content

Commit 2566b26

Browse files
committed
sec: enhance API fetcher to handle absolute URLs and improve config merging
1 parent 7edb6cf commit 2566b26

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

src/api-handler.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
} from './types/api-handler';
1818
import { fetchf } from '.';
1919
import { mergeConfigs } from './config-handler';
20+
import { isAbsoluteUrl } from './utils';
2021

2122
/**
2223
* Creates an instance of API Handler.
@@ -99,22 +100,25 @@ function createApiFetcher<
99100
FinalParams<ResponseData, UrlParams, UrlPathParams>
100101
>
101102
> {
102-
// Use global per-endpoint settings
103-
const endpointConfig =
104-
endpoints[endpointName] ||
103+
// Use global and per-endpoint settings
104+
const endpointConfig = endpoints[endpointName];
105+
const _endpointConfig =
106+
endpointConfig ||
105107
({ url: String(endpointName) } as RequestConfigUrlRequired);
106-
const url = endpointConfig.url;
108+
const url = _endpointConfig.url;
107109

108110
// Block Protocol-relative URLs as they could lead to SSRF (Server-Side Request Forgery)
109111
if (url.startsWith('//')) {
110112
throw new Error('Protocol-relative URLs are not allowed.');
111113
}
112114

113115
// Prevent potential Server-Side Request Forgery attack and leakage of credentials when same instance is used for external requests
114-
const isAbsoluteUrl = url.includes('://');
115-
const mergedConfig = isAbsoluteUrl
116-
? mergeConfigs(endpointConfig, requestConfig)
117-
: mergeConfigs(mergeConfigs(config, endpointConfig), requestConfig);
116+
const mergedConfig = isAbsoluteUrl(url)
117+
? // Merge endpoints configs for absolute URLs only if urls match
118+
endpointConfig?.url === url
119+
? mergeConfigs(_endpointConfig, requestConfig)
120+
: requestConfig
121+
: mergeConfigs(mergeConfigs(config, _endpointConfig), requestConfig);
118122

119123
// We prevent potential Server-Side Request Forgery attack and leakage of credentials as the same instance is not used for external requests
120124
// Retrigger fetch to ensure completely new instance of handler being triggered for external URLs

src/config-handler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
isSearchParams,
2121
isJSONSerializable,
2222
isSlowConnection,
23+
isAbsoluteUrl,
2324
} from './utils';
2425

2526
const defaultTimeoutMs = (isSlowConnection() ? 60 : 30) * 1000;
@@ -107,7 +108,7 @@ export const buildConfig = (
107108
// The explicitly passed query params
108109
const dynamicUrl = replaceUrlPathParams(url, requestConfig.urlPathParams);
109110
const urlPath = appendQueryParams(dynamicUrl, requestConfig.params);
110-
const isFullUrl = urlPath.includes('://');
111+
const isFullUrl = isAbsoluteUrl(url);
111112
const baseURL = isFullUrl
112113
? ''
113114
: requestConfig.baseURL || requestConfig.apiUrl || '';

0 commit comments

Comments
 (0)