Description
The Custom OAuth provider's getAccessToken function in app/custom-oauth/server/custom_oauth_server.js calls fetch() (from @rocket.chat/server-fetch) without passing the allowList option. This means the SSRF_Allowlist admin setting is completely ignored during OAuth token exchanges.
This makes it impossible to use Custom OAuth with an identity provider on a private IP (e.g., 192.168.x.x, 10.x.x.x) in self-hosted/homelab deployments, even when the administrator has explicitly allowlisted the host in Administration > Settings > General > SSRF Protection > SSRF Allowlist.
Steps to Reproduce
- Deploy Rocket.Chat 8.2.0 self-hosted
- Configure a Custom OAuth provider pointing at an IdP on a private IP (e.g., WSO2, Keycloak, Authentik at
https://idp.local:9443)
- Add
idp.local and its IP to the SSRF Allowlist in Admin > General > SSRF Protection
- Click "Login with [Provider]"
Expected Behavior
The SSRF allowlist should permit the token exchange request to the allowlisted host.
Actual Behavior
The token exchange fails with:
SSRF validation failed for URL https://idp.local/oauth2/token
Error: Failed to complete OAuth handshake with [provider] at https://idp.local/oauth2/token. error-ssrf-validation-failed
Root Cause
In app/custom-oauth/server/custom_oauth_server.js, the getAccessToken method calls:
const request = await fetch(`${this.tokenPath}`, {
method: 'POST',
headers,
body: params
});
This does not pass allowList: settings.get('SSRF_Allowlist') in the fetch options.
Compare with other internal fetch calls (e.g., in app/apps/server/bridges/http.ts line ~131765) which correctly pass:
{
allowList: settings.get('SSRF_Allowlist')
}
The same issue applies to the getIdentity method which also calls fetch() without allowList.
Suggested Fix
Pass the SSRF allowlist to all fetch calls in the Custom OAuth module:
const request = await fetch(`${this.tokenPath}`, {
method: 'POST',
headers,
body: params,
allowList: settings.get('SSRF_Allowlist')
});
Impact
This affects all self-hosted Rocket.Chat deployments where the OAuth/OIDC provider is on the same private network. This is the standard deployment pattern for homelabs, on-premise enterprise, and air-gapped environments.
Version
- Rocket.Chat: 8.2.0
- Node.js: 22.16.0
Workaround
Patch @rocket.chat/server-fetch/dist/helpers.js via an init container to whitelist the specific private IP in the isIpInAnyRange function.
Description
The Custom OAuth provider's
getAccessTokenfunction inapp/custom-oauth/server/custom_oauth_server.jscallsfetch()(from@rocket.chat/server-fetch) without passing theallowListoption. This means theSSRF_Allowlistadmin setting is completely ignored during OAuth token exchanges.This makes it impossible to use Custom OAuth with an identity provider on a private IP (e.g.,
192.168.x.x,10.x.x.x) in self-hosted/homelab deployments, even when the administrator has explicitly allowlisted the host in Administration > Settings > General > SSRF Protection > SSRF Allowlist.Steps to Reproduce
https://idp.local:9443)idp.localand its IP to the SSRF Allowlist in Admin > General > SSRF ProtectionExpected Behavior
The SSRF allowlist should permit the token exchange request to the allowlisted host.
Actual Behavior
The token exchange fails with:
Root Cause
In
app/custom-oauth/server/custom_oauth_server.js, thegetAccessTokenmethod calls:This does not pass
allowList: settings.get('SSRF_Allowlist')in the fetch options.Compare with other internal fetch calls (e.g., in
app/apps/server/bridges/http.tsline ~131765) which correctly pass:The same issue applies to the
getIdentitymethod which also callsfetch()withoutallowList.Suggested Fix
Pass the SSRF allowlist to all fetch calls in the Custom OAuth module:
Impact
This affects all self-hosted Rocket.Chat deployments where the OAuth/OIDC provider is on the same private network. This is the standard deployment pattern for homelabs, on-premise enterprise, and air-gapped environments.
Version
Workaround
Patch
@rocket.chat/server-fetch/dist/helpers.jsvia an init container to whitelist the specific private IP in theisIpInAnyRangefunction.