RocketChat / RocketChat/Rocket.Chat
Custom OAuth token exchange ignores SSRF_Allowlist setting
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 46.1k
- Forks
- 13.9k
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 130
Description
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.localand 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in app/custom-oauth/server/custom_oauth_server.js and inspect the getAccessToken and getIdentity fetch calls, then compare their options with the allowList usage in app/apps/server/bridges/http.ts. Done means both Custom OAuth requests honor settings.get('SSRF_Allowlist'), allowing configured private hosts while preserving SSRF validation for other hosts.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- backend, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100