TLDR: I found a vulnerability in the way the Discord clients parse URLs which makes my custom embed content appear to come from a legitimate domain.
https://discord.gg%2ek.vu will show an embed from
https://discord.gg.k.vu but display as
Discord uses Node’s
url.parse()function to process URLs in messages. Node’s parser expects to receive a URL which has already had its percent encoding decoded into special characters. Discord’s web and desktop clients forget to do this and instead attempt to parse the raw user input.
% symbol is never allowed in a hostname (ietf.org/rfc/rfc2396.html#section-3.2.2) so the parser considers the hostname as the text before the
%. This results in the server (which decodes the
%2e to a
.) and the client seeing different URLs.
$ node parseUrl.js "https://discord.gg%2ek.vu"
The server which loads the embed content acts the same way as a normal web browser and decodes the
%2e before loading the embed from
https://discord.gg.k.vu. The desktop and web clients incorrectly parse the URL and display it as
https://discord.gg/%2ek.vu, suggesting that the URL came from
This vulnerability can be used for much more realistic phishing attacks as the blue text that the user is clicking is different to the website that it links to. For example, clicking “Join the Official Fortnite Discord Server!” in the image below sends the victim to a cloned Discord login page. The user has just seen the
discord.gg URL so they are unlikely to be suspicious of the login page.
I contacted Discord security about this vulnerability and they claim that it is not a security vulnerability as “there is no guarantee the link in a message matches the link in the title.” As such, there is no patch available and all desktop and web clients are currently vulnerable. Mobile devices do not display the deceiving slash.