RocketChat / RocketChat/Rocket.Chat
setUserAvatar.ts fails if avatar URL is in the private range.
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 46.1k
- Forks
- 13.9k
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 130
Description
Description:
For some reason checkUrlForSsrf.ts has been updated so that it checks the IP address of a resolved domain name and fails if it's in a private range. It does fall in the private range, and returns a fairly meaningless error "Error: Invalid avatar URL".
Steps to reproduce:
When calling /api/v1/users.setAvatar
and passing "http://a.server.com/tools/getfile.php?a=8613&u=07f40e8b-ab27-48aa-9fe9-4e079e7f8c50&f=2964"
as "avatarUrl", which is a valid URL and returns an image.
Expected behavior:
"success": 1
and the avatar to update.
Actual behavior:
{"level":35,"time":"2025-01-23T15:20:02.154Z","pid":1,"hostname":"664a2fb55780","name":"API","method":"POST","url":"/api/v1/users.setAvatar","userId":"xxxxx","length":"142","host":"10.1.1.83:3001","remoteIP":"10.1.1.60","err":{"type":"errorClass","message":"Invalid avatar URL: http://a.server.com/tools/getfile.php?a=8613&u=07f40e8b-ab27-48aa-9fe9-4e079e7f8c50&f=2964 [error-avatar-invalid-url]","stack":"Error: Invalid avatar URL: http://a.server.com/tools/getfile.php?a=8613&u=07f40e8b-ab27-48aa-9fe9-4e079e7f8c50&f=2964 [error-avatar-invalid-url]
at app/lib/server/functions/setUserAvatar.ts:95:11
at setUserAvatar (app/lib/server/functions/setUserAvatar.ts:89:27)
...
Resolution
Remove private ranges from this function, there is no reason why a URL needs to resolve to an internet address, and I'm not sure why this would be added, especially when the API request is coming from 10.1.1.60, to 10.1.1.83 which is rocket.chat.
Removing 10.0.0.0/8 from the structure resolves the issue.
Server Setup Information:
- Version of Rocket.Chat Server: 7.2.1
- License Type: Community
- Number of Users: 20
- Operating System: Linux
- Deployment Method: docker
- Number of Running Instances: 2
Additional context
the URL http://a.server.com resolves to 10.1.1.60 which is an internal web-server tasked with providing support functions.
checkUrlForSsrf.ts defines a series of private ranges;
const ranges: string[] = [
'0.0.0.0/8',
'10.0.0.0/8',
'100.64.0.0/10',
'127.0.0.0/8',
'169.254.0.0/16',
'172.16.0.0/12',
'192.0.0.0/24',
'192.0.2.0/24',
'192.88.99.0/24',
'192.168.0.0/16',
'198.18.0.0/15',
'198.51.100.0/24',
'203.0.113.0/24',
'224.0.0.0/4',
'240.0.0.0/4',
'255.255.255.255',
'100.100.100.200/32',
];
and then, for some unknown reason rejects a url that resolves to one of those ranges. This is a recent change.
The error produced does not provide any useful information on why the URL was rejected, and it should as it does for all the other possible failures.
Regardless, why would you block avatar updates from internal servers? This is running in docker, most things are internal.
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 with app/lib/server/functions/setUserAvatar.ts, especially the call around lines 89-95, and review checkUrlForSsrf.ts and its private-range definitions. Reproduce the POST to /api/v1/users.setAvatar using the supplied avatar URL, then inspect existing tests or validation paths. Done means the intended handling of internal avatar URLs is established and the rejection behavior provides useful error information without weakening SSRF protection unintentionally.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100