Coding the Shield: A Deep Dive into the Development of the Discord Bot that Blocked 1000+ Phishing Attacks
Tags: javascript, security, discord, node
Published: 2024-01-08 14:48:30

## What This Article is About

In this article I'll talk about one of my favorite side projects I worked on, **Postman Sentinel**. Well technically it was first called **Postman Student Helper** when it was first developed 3 years ago. I'll go into depth about how and why I built this project, how I received help from the Postman Community and it's impact. Also I'd like to mention that this is my first blog post so I would love to receive constructive feedback about my writing. Happy reading!

## The Backstory

Back in 2021 when I was still in university as a 2nd grade IT student I've wanted to do a lot of community work. At that time I got accepted to an awesome student program called [Postman Student Leaders](https://www.postman.com/student-program/student-leader/). All the communication in the community was and still is done via Discord. If you don't know Discord it's basically a massive communication platform for communities and friends.

Now the problem was during that time there was a massive increase in scammers in Discord. It was mostly Discord Nitro Scams because at that time Epic Games was giving away free Discord Nitro. So the scammers were constantly spamming messages with malicious links. Here is an example message:


![Example Phishing Message](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0jot8r6zev31xqujsbii.png)

## What's Going On?

I've blurred the user of the account at top because these phishing links were sent from hacked accounts in an automated matter. Messages like these were sent in all the text channels multiple times on random times of the days. Basically the link is similar to discord as can be noticed. It's usually something like **disord**, **discorde**, **diiscord** etc. Texts that can deceive users when checking the message quickly. The link has a clone of the Login Screen of Discord. Something similar or basically the same as this:

![Discord Login Screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zzqxiyx5t6gipfjwtqw.png)

When the user writes their user credentials they are then sent to the server of the scammer. Now the scammers have the email and password of the users. After that the website redirects them to the actual Discord login screen. So most of the users think something went wrong and login again. Most of them are not aware that their account credentials have been stolen and if they do not have 2FA in their account, their account is now part of a botnet that automatically sends messages to Discord servers.

## The Problem and The Solution

Obviously the problem was that our server had quite bit of people and due that even if we acted fast enough and deleted the messages quickly, if at least 2 people clicked on that link, infected account amount increased.

This was a major problem because usually we weren't fast enough. Only certain verified people had permissions to delete messages and manage the server. So we would have to write to these certain people that there are phishing links in the server. Sometimes no one with right amount of permission would be online and these messages could stay in the chat for hours.

That was the moment I thought I could probably help the community and develop something great. I already had some experience developing Discord bots with Discord.js. I recently built a bot for my friends to use so I thought I can build one that can actually automatically detect these messages and delete them from the chat.

## My First Implementation Worked But Was Not Efficient 

Well back then I was still a student and had nowhere near the knowledge of software development as of now. I wanted to build something pretty fast due to these phishing links being constantly sent. I went with the easiest and fastest solution I could think of and that was scanning every message sent for the keyword **nitro**. It was nowhere near the perfect solution but it got the job done.
```javascript
message.content.toLowerCase().includes("nitro")
```
This surprisingly worked really, really well. It blocked almost all of the phishing links. Although as you can see this is far from a good solution. After a month some scammers started to send just the links and no text. So the bot failed to block them since there was no "nitro" in the message they sent. This solution was also prone to a lot of false positives. A lot of innocent messages were also deleted.

## A Helping Hand From Postman

I don't know if I mentioned it but I made this project open-source from start. This was mostly because I wanted to have a community of developers working on this bot and improving my code. Well, I got what I wanted. **Claire Froelich** from Postman helped me a lot with the project. She introduced me to concepts like Prettier and cleaned a lot of my poorly written code. She also added probably the best feature of the bot which is an actual phishing link detection using Levenshtein Distance algorithm. 

The algorithm basically compares two strings and gives a result on how similar these two strings are. This was really useful because now we can target specific urls and delete messages that are similar to these urls.

Here is the first version of that code:
```javascript
import { distance } from "fastest-levenshtein";

/** Most spam links try to typosquat 'discord' to trick users into thinking the link is safe (ex: "discorde")*/
const TYPOSQUAT_TARGET = "discord";

function isSuspiciousLink(link, threshold = 4) {
    // get base domain
    const matches = link.match(/^https?:\/\/(\S+?)\./);
    if (!matches) return;
    const base = matches[1];
    // check levenshtein distance of domain to "discord"
    const d = distance(TYPOSQUAT_TARGET, base);
    // if distance is > 0 and < threshold, base is typosquating. Call foul
    if (d > 0 && d <= threshold) {
        return true;
    }
    return false;
}

export { isSuspiciousLink };
```

This solution worked perfectly and we mostly moved with this solution changed some values or made improvements according to data from false positives.

Because of this we could easily add other websites to check as well such as GitHub. Eventually scammers used different links like posting a fake github link similar to the Discord Nitro scam links. Here is an old photo of these messages being detected and deleted automatically.


![GitHub Phishing Links being deleted](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7972bg8jt56a5zgrhrb.png)

This bot had other fun features as well such as fetching and posting coding memes from Reddit

![A coding meme sent by Postman Sentinel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t8xgzvv9hmeyq9k2o21j.png)

## Why Go All This Trouble?

Working on this project was a really fun experience. I learned a lot about hosting, cloud, Docker, Node.js and working as a team. But one of the main reason I continued on development back in the day was seeing the impact it provided.


![Image of appreciation from community](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bsjsqoqn8o1loe2reff.png)

This project was my first real world project that actually helped and provided something to people. I could see the impact it made, the blocked messages, time saved from community staff and accounts saved from scammers.

Seeing that really motivated me to keep the bot running and updating it according to latest phishing attempts at the server.

It also became my best side projects in my resume. I remember talking with recruiters about the bot for a large portion of the interview and answering their questions. It's really awesome to have an unique project that provides real world value to a community.

So if you're in a community and see something you can improve, go for it! Even if you're a beginner like I was at worst case scenario you'll have a cool side project.

If you wish to check out the project [here is the GitHub link](https://github.com/ctnkaan/Postman-Sentinel) it's pretty old so I might need to update my old code. Feel free to contribute!