(Previously reported via security channels, was rejected, now doing public disclosure following a responsible disclosure process)
Summary / Request
As a user, I want the hotlinked images posted to chat to be cached by server, and only then shown to me in order to protect my IP from a nefarious third-party image hosting server. I do still want to see the cached/proxied image, though!
Discourse already has settings for this, but they’re not applied correctly to chat. Having both relevant hotlinking settings (below) enabled should act the same as the forum. IE: the third-party hosted image is downloaded to the server, and only then shown to the user.
Background / Impact
In the oldendays of internet forums, it was quite popular to let users post image embeds by “hotlinking” to third party servers hosting the images.
While this was quite common with older forums, as the internet advanced we learned this was a bad practice. Almost all social media platforms evolved to prevent this. Part of the reason was to avoid problems with broken/lost images, or overloading small servers, but there is a very important security consideration as well:
A user posting an image from an offsite server downloads that from the linked server. This allows a malicious third party server to log the user’s IP. This is quite problematic as if the server is run by a nefarious user, they now know the IP of the other user. (Imagine a case where a nefarious user messages you to discover your home IP)
A leaked IP can be used by a nefarious person to determine the true identity of the user or to scan their home router / PC for vulnerabilities, etc. You might even be able to do an XSS with it on another site if the other site has any XSS vulnerabilities.
This is why pretty much every major social network (Twitter, Discord, Facebook, etc) doesn’t do image hotlinking anymore for security reasons. Every third party image is now cached on the server instead of having the user pull it directly.
Relevant Discourse Settings
Discourse provides two relevant settings:
Block hotlinked media
will replace hotlinked images with a text link instead.
Download remote images to local
will convert hotlinked images to locally stored images.
Setting Behavior in Forum
With both these settings enabled, the forum appears to work as expected in my limited testing. External images are converted to local images before they are shown to other users, protecting the user’s IP. I have not tried extensive timing attacks to verify the behavior, but at least in my limited testing it worked correctly.
(This is what I’d expect for any modern social platform, similar to behavior on Twitter/Discord/Facebook etc)
Setting Behavior in Chat
On the chat, I was not able to get similar behavior. No combination of settings yields satisfactory results:
Having both settings enabled converts the remote image to a link only. However, there is a very short window of time the image still is shown to the other user and thus makes a web request, exposing the user IP to the other user. This is basically the worst result, since user IP is exposed and you don’t even get to see the image.
Having
Block hotlinked media
disabled and Download remote images to local
enabled just does a hotlink; it didn’t seem to actually download the remote image. Not a vulnerability, but seems like a bug.
Having
Block hotlinked media
enabled and Download remote images to local
disabled has the same behavior as having them both enabled. It shows as a link instead of an image – but the image is sometimes pulled by the remote client, exposing the IP. (I found sometimes the first time the image is sent it would block it, but the second time briefly wouldn’t, or other probably timing-related issues happening frequently.)
(Re-tested on a development checkout from git today: 3.5.0.beta8-dev (2c0635ee4c))
Disclosure / Response
I reported this previously (in 2024) via e-mail and hackerone, but was told it was not a security issue and the security report (2844784) was rejected, unfortunately. Here was the relevant statement:
Thank you for your report. After careful review, I’m closing this since the described behavior is standard web functionality rather than a security vulnerability.
When a browser loads any external resource (images, scripts, etc.), it necessarily makes a request to the hosting server. This server will naturally see the requesting IP address - this is fundamental to how the internet works and is not considered a security vulnerability on its own. While IP addresses can be considered personal data in some contexts, their exposure through standard web requests is an expected behavior that users implicitly accept when browsing the internet.
The hotlinking protection in Discourse is designed to prevent unauthorized reuse of hosted content, not to hide user IP addresses from external servers.
This may well be the intended usecase of the hotlinking blocking feature, but I do think not addressing this puts chat plugin users at risk – especially in more rambunctious communities that may have users that would try to find a foe’s home IP and doxx/DDOS them.
I object also to the idea that users implicitly consent to accessing untrusted hotlink URLs on a trusted forum site in the modern era. I won’t comment about GDPR/etc implications as I don’t know them, but just from a basic privacy expectation, this is not expected except on very old forums. Definitely not modern era ones.
I informed of my intention to post publicly on this forum about the issue on Nov 22, 2024 and heard nothing back since then.
I’m posting here so other discourse admins can be aware and hopefully encourage the hotlinking protection to be improved by the engineering team. As it has been a long time and no improvement, I am posting in good faith in the hope awareness and perhaps community encouragement on the importance of the issue will bring improvement.
Thanks for reading