Phishing on Hive? No more. Solution for all Frontends.

in HiveDevs3 years ago (edited)

One   script   to rule them all..


In the past few weeks Hive has been plagued by phishing campaigns and some users lost access to their account or lost their funds. This is nothing new and has been going on for years on Steem and Hive.

To make things worse, registrars are not quick enough to take down phishing domains..

It is time that the Hive community tries to mitigate this issue on their own.

Potential solution:
Use a plug-and-play universal script (or a modified copy of it) that all Hive frontends can integrate to block phishing links in a timely matter. As soon as a phishing campaign starts on Hive and the attacker's domain is spotted and added to a blacklist API (eg. @spaminator's), the universal script would immediately block the attack in all Hive frontends and at the same time leave the User Experience unaffected.

As a matter of fact, this is what I worked on in the past few days.

NOTE : the demo page will not be sanitized by my universal script until you: 1. Navigate to and click on the "Request temporary access" button, 2. refresh the demo website.

I have proved my universal script working on:      (see screenshots down below)

HIVE.BLOG - - @blocktrades @quochuy
PEAKD - - @asgarth, @jarvie
LEOFINANCE - - @khaleelkazi
ECENCY - - @good-karma
3SPEAK - - @theycallmedan, @starkerz
D.BUZZ - - @chrisrice
STEM social - - @lemouth
STEM geeks - - @enforcer48 ?

It would be great if each Hive frontend maintaner could review it and adapt it to their needs (if they need to -- I tested this script in all major Hive frontends already and it did not seem to have unwanted side effects). I highly recommend though that the integration is thoroughly regression tested before it's used in production.

FYI also for:
AnonRamblings @emrebeyler, DTube @heimindanger, Engage @arcange, Engrave @engrave, @nicniezgrublem, Hive-db @jesta, Hive-Engine @aggroed, Hiveblockexplorer @penguinpablo, Hiveblocks @roadscape, HiveEngine @holger80, Quello @tobias-g, ...
+ other project maintaners: @yabapmatt, @stoodkev, @aggroed, @louis88, @mahdiyari, @acidyo, @fbslo, @rishi556.
(apologies for the mass tag)

I believe that blocking phishing campaigns in an unified way in all frontends is possible despite the different tech stacks in use. It does no matter which framework the website maintainer used to develop their website (eg. ReactJS, AngularJS, VueJS, JQuery, vanilla JS, etc). Using JS global overrides it is possible to prevent users from falling victim of phishing.

What does my script do?

It uses the native APIs offered by all browsers in order to immediately block phishing links and images in all Hive frontends as soon as they are discovered and published into the blacklist.

  • Any known phishing link in the UI will be red and strikethrough-ed. Furthermore if you click on a known phishing link you'll see an alert telling you that it's phishing and it won't allow you to navigate to the phishing domain from the Hive frontend.

  • Any image that is marked as a phishing attempt (eg. an image with some text saying "claim your $ 1000 in tokens at") will not be displayed in any frontend that uses my script (or a variant of it) as soon as its URL is published into the public blacklist.

More details will follow towards the end of the post to list all the native features of the browser that are hardened by my script in order to prevent phishing (ie. iframes, scripts, window open, XHR requests, Fetch api).


How difficult is it to try out my universal script in your Hive-powered website?

Integrating this script is very straightforward. In order to integrate it, simply add a tag to the head section of your index.html page. That's it!

Your index.html :

    <script src=""> 

This should be enough for your tests. Some intial recommendations though:

  • Keep an eye on CORS issues. If a request is failing because of CORS, use for your tests (it's already there commented out in my script).
  • Update your Content Security Policy if necessary to allow your website to load my script from Github and to allow the request to @spaminator's api to go through.
  • It is highly recommended that you host your own version of this script for your production website. It is clearly not a good idea to rely on my github as it's a single point of failure. For example, what if my github account gets compromised? If all Hive frontends point to my script they would all be affected!

And now.. some proof of this thing working:

Overview of protected features on various Hive Frontends


[screenshot taken after applying my script to Leofinance]

styling applied to known phishing links: red and strike-through

alert displayed when a known phishing link is clicked:

(my comment:

Other frontends:

[screenshot taken after applying my script to 3speak]

[screenshot taken after applying my script to]
(my post:

[screenshot taken after applying my script to Stem social]

[screenshot taken after applying my script to Stem Geeks]:
image.png .


Both "img" tags and direct uploads get correctly sanitized:

[screenshot taken after applying my script to]


Eg. malicious ads - see this phishing campaign

[screenshot taken after applying my script to]


[screenshot taken after applying my script to Peakd]


[screenshot taken after applying my script to Ecency]


Not supported by my universal script:

  • window.location (window.location.replace(url) and assignments to window.location.href)
    The window.location object is immutable therefore if you use that approach to open external lilnks, please consider switching to so that my script will protect your user base from known phishing domains.

Potential improvements:

  • Instead of just using a list of known phishing domains, the blacklist could be restructured to something similar to what I'm currently using for @keys-defender's blacklist (merged with the @spaminator's one).
    Instead of just using a list of links, I use an array of objects and each object has the following properties:
    -- "regex": used to match a known phishing domain
    -- "fullLink": full link to the homepage of the phishing site
    -- "threatType": PHISHING or COMPROMISED_DOMAIN. I used the latter in the past when I found a critical vulnerability in a Hive website and only until it got patched. This attribute is also used in @keys-defender auto-replies to phishing comments to categorize threats.
    -- "infoBlog": link to article that warns against the phishing campaing in progress. This is already in @keys-defender auto-replies and if none is provided it defaults to an intro post.
              If we had multiple blacklists and they all shared this interface (eg. using a swagger file) it would be easy to merge them and use them to block phishing campaigns in their early stages. The warnings displayed to the users would be more accurate as well.
  • Add a warning to all Hive frontends for all comments containing links left by known compromised accounts. This should be easy to add re-using the global overrides already added in my script and @spaminator's api dedicated for this purpose.
  • Display a proper message on the UI instead of just an alert (probably not important, a fancy UX in my opinion is not necessary for this edge case). Hive frontends maintainers can adjust the messaging as they see fit though. My alerts are more of a Proof of Concept after all.


  • Centralization. Despite being a good start, we should not rely only on @spaminator's API. Some potential solutions to this is to allow users to choose which blacklist to use, or fetch multiple blacklists at the same time. Or even have each Hive website maintainer host their own blacklist.

  • No load testing was performed on @spaminator API. If all Hive frontends start using their API it may become an issue. @spaminator team to chim in on this.
    The requests from my script are already throttled significantly on the client side and a local cache is used as well.

  • Proper server-side caching on @spaminator API. Eg. Cache-Control response header set to 5 mins? Cloudfront (AWS) caching / Varnish / Redis?

  • Scaling. How scalable is @spaminator API? Would they incur in prohibitive cost if too many requests were to be sent daily? Do they have a defense mechanism in place for DDOS attacks? This is not a deal breaker since all users will have a cached version of the blacklist, but an attacker could try and take advantage of this for a new phishing campaign.

Notes for devs that try my script:

  • To turn OFF verbose logging and remove the cors-anywhere proxy, set IS_DEBUG to false.
  • @spaminator's list of blacklisted domains lives at This list of known phishing domains targeting Hive is stored in the localstorage as well. If the API is down (eg. DDOS-ed) the Frontends will still block known phishing domains.


  • The list of global overrides added in my script is: document.createElement, element.setAttribute and getAttribute, history.pushState, XMLHttpRequestClass, window.fetch,

  • The DOM elements sanitized by my script are: iframe, script, img, a. Other potential candidates that would be easy to cover: input, audio, embed, source, track, video, link.

  • When the document is fully rendered all the risky elements (anchors, images, etc) are checked again if they weren't already. Eg. comments fetched after the page is fully loaded.

  • In order to reduce the load on @spaminator's servers, if the user is idle on a page the API is queried again only every 15 minutes. If the user navigates to a different subpath of a Single Page Application (eg. (would not cause a page refresh) the api is queried only if at least 5 mins passed from the last query.
    The same applies for non-SPA (eg. Leofinance, Peakd). A new API request to fetch the updated list of domains is sent only if more than 5 minutes passed from the last request.
                                              Example of phishing domains fetch on history change

  • Metrics - I added some timers and I noticed no significant performance impact validating all risky elements against the list of known phishing domains.

  • The script is already resilient to API 500 responses (eg. DDOS-ed). We could also periodically rotate to different APIs or fetch multiple ones at the same time.

  • Here is a link to my script transpiled with BabelJS for older browsers and minified to save some milliseconds in the load time:

  • Test it!

To reiterate, before using this script in production it is highly recommended that you perform regression testing to make sure that existing features are not affected by the global overrides in my script. From my own tests they seem to all work correctly but this should not be put in production as is without review and further testing on each Hive frontend.

Are you bored with your day and willing to read more?

If you're not tired of hearing me rumble about this stuff in your head, here is some more stuff to read..
Why did I decide to work on this solution?
There were some discussion ongoing on Discord and Slack about how to timely react to phishing campaigns that recently plagued Hive. @guiltyparties and @pfunk claimed that our best shot would be to block dangerous links directly in the Hive frontends.


This though required every single maintainer of the Hive condensers to implement their own logic from scratch in order to block attackers.


The idea I already have had in mind for a while though was to use a single script, as an universal solution for most Hive frontend out there.

I had already worked on something similar for a client of my employer. It was not for phishing, but the same logic applied. The platform I was working on used a custom scheme (eg. somescheme:// instead of https://) and all relative protocol links added by third party scripts (eg. "//") were defaulting to the custom scheme instead of using HTTPS.
In that occasion I had to use some global overrides to add the https prefix to anything that was meant to go out to third parties. That ended up being handy for this solution on Hive.

When did I work on this Proof of Concept for Hive frontends, you ask?
Late at night in the past few days while caring for my few-days-old newborn. I'm off work and getting bored so I decided to put my sleep deprivation at work and started writing some code for this purpose. I hope it will be useful and get used to effectively improve our Hive frontends and discourage scammers.

Keys-Defender features:

- Keys protection[live scan of transfers / posts / comments / other_ops. Auto-transfers to savings, auto-reset of keys, ..] {see automatic posts on leak and monthly reports}
- Phishing protection [live scan of commentsa and posts to warn users against known phishing campaigns and compromised domains, scan of memos]
- Re-posting detection [mitigates the issue of re-posters]
- Code injections detection [live scan of blocks for malicious code targeting dapps of the Hive ecosystem]
- Anti spam efforts [counteracts spam from hive haters]

Take care,
@keys-defender (@gaottantacinque)

Please don't forget to upvote and reblog. Donations are welcome as well, those damn diapers aren't free!   =P


This is now implemented on 3speak! Hopefully the other platforms will do the same.

That’s great to hear!! And wow, that was fast!   =]

Excellent module. Will be integrating this on DTube within this week and maybe have the list hosted on Avalon APIs with potentially additional domains I might spot on Avalon (so far haven't seen any).

That’s awesome 😎 👏

Seems like a good solution as I am sure the community can spot new phishing fairly quickly, but some people will never see warning posts. Hope to see it adopted soon.


It looks like 3speak already integrated it! 🤩

That looks pretty cool!
Every measure that can reduce the chance of people falling victim to a phishing attack should be considered.

Any known phishing link in the UI will be red and strikethrough-ed.
So, is it using a database of known phishing links? The only pitfall would be that people immediately trust links that are not in this database yet and therefor not striked-through.
But then again you will save a lot of peoples keys too.

Posted Using LeoFinance Beta

Yes it is using @spaminator’s list of known phishing domains:

Every time a new phishing wave starts, the attacker’s domain gets added there by the @spaminator team.

Maybe you’re right. That’s also why I was thinking that we should automate the addition of new entries to the blacklist. What I had in mind for this was:

  • If a top 20 witness sends a memo like “” the reported domain gets automatically added to the blacklist;
  • Same if at least 2 witnesses in position between 40 and 20 send a memo in that format.
I could even host myself a copy of @spaminator's blacklist and start offering this automation mechanism in @keys-defender..
🤔💡 - PS. DONE

Seems like a good plan!

Posted Using LeoFinance Beta

That is great. I saw a phishing comment on a post last week but could tell it was bogus. It lead to a faked Hivesigner page that stole peoples keys if they tried to log in.

Glad you guys are killing it.

Posted Using LeoFinance Beta

Yep the same attacker has been leading 5 different phishing campaigns and they all ended with that fake hivesigner. Unfortunately some people didn’t realize it was bogus so I kept submitting with a script thousands of potentially valid credentials to make the attacker’s life more difficult 😉

For you might want to reach out to @themarkymark for technical support.

Good initiative! Would be great if you could tag a release though.
From Keychain, we are displaying warnings when about to transfer to accounts listed as bad actors on condenser.


Couldn't there be a way to integrate the user selected blacklist systems that are being integrated directly into hivemind and condenser and platforms are already working on integrating.

It should be feasible. Is there a documentation page I can look at? Thx

@asgarth or @blocktrades may have a link to that specifically.

On your side from what I understand Seems as simple as muting that account with an account setup specifically to identify phishing. Then a UI implementing some features for that (maybe some of what you have created not sure)

But holding of this information and referencing by the platforms is what I'm looking at... with mute lists seems so easy.
Create an account phishing.defense add a description to the account that UIs could also use and users could understand and then just mute all the users in your list. Doesn't need some new random centralized api. It comes with all the features we know how to use on hive. We can view all this stuff easily.

Or maybe I'm missing something regarding what you're doing.

users could understand and then just mute all the users in your list

I am not very familiar with mute lists yet so I'll need to read some docs. I think that the only problem with mute lists is that when phished users re-gain access to their account they would still be muted. So that would require some manual steps to blacklist/whitelist users all the time. Doable but I'm wondering if it's the right approach and effective enough.

The whole point of this first version of my script is not about preventing a single user spamming phishing links. It would not be effective focusing on preventing that because usually the attacker has many accounts, can create more or use the newly phished accounts to keep spamming more phishing comments. I think what's more effective is blocking the known phishing domain itself.

Definitively centralization is a concern, as stated the post. We should have redundancy in place. As per comment above I think I will also host a copy of the blacklist myself and add some automation to it to allow trusted users (witnesses) to add new phishing domains to the list.

This is also what I am in favor of @jarvie . . in fact, we are scheduled to release @blocktrades' Decentralized Blacklists / Mutelists solution on this Tuesday.

  • Red lining suspected phishing domains is also a decent idea, but it should be opt-in @keys-defender, and there should be more than one list of suspected phishing domains, and it should be handled by more than one person / groups of people.

Opt-in + Multiple Choices, decreases centralization and in the end, censorship.

Exactly what I stated in my post.

  • I’m not part of the spaminator team and I’ll start offering my own known phishing domains list with some automation in place to allow trusted members of the community to automatically add new domains to the blacklist

And yes, we agree but it’s up to the frontends to let users choose which blacklist (if any) to use. IMO at least one should be ON by deafault though in order to protect them.

  1. Yeah, you're right, there should be a default blacklist with an opt-out option though.

  2. If you create a Blacklist / Mutelist like @jarvie mentioned, I can consider using it for D.Buzz

  3. I want there to be a tool where any user can create a list of domains that would be lined out in red, and that their list could be followed by any other user.

#3 would decentralize the service you are offering.

You replied to your own comment instead of on @keys-defender's comment. 🤨 Therefore, they would not receive a notification. 😒 Anyway, this comment is enough for them to get notified of your comment. 🤨🤨

1 - we already have 3 phishing domains blacklists available. When I have time I'll release a new version of this script that uses them all, including the phishing links reported by the community (see my latest post). It will be up to the frontends to offer a way to let the user choose which one to use or to opt-out. My code will make the integration simple.
2 - blacklists and mutelists are to mute users and that's not effective because phishers keep rotating new accounts in their attacks.
3 - that seems like a feature for the core dev team.

It looks like @dbuzz can rest from marking posts with phishing links as blatant scam on D.Buzz. 🤔

Tried to integrate your script in my Engage app but it just broke it. I'll analyze why more in depth later.

Haven’t tried yours, will do tonight

@arcange it worked fine for me:


  • What are your symptoms?

All good now.
I guess I made the change late at night and inserted your code at the wrong place. I was too lazy tired to debug and rolled back before going to sleep, which was the best decision.

I use my Android phone to access and publish. Should I avoid any front-end site or app? Or prefer some others? Are there any safe Android apps? Like Ecency for example?

No afaik there isn’t one you should avoid. The majority of Hive users use peakd and it probably has the biggest development team so it may be safer than others only maintained by a single dev.

I haven’t tried Hive mobile apps in a while. The last one I tried was esteem years back but it was too buggy.
If it’s a fully native app they would have to implement their own anti-phishing solution, if it’s a hybrid app (ie. a native wrapper around a web app) then they should be able to use my script too.

Thanks for the answer. Any ideas how all these accounts were hacked recently?

Seems like there might be a slight problem with turbolinks compatibility. I'll investigate later.



Ah, same issue that had. What’s your domain? I’ll add it to isSupportedSite()

I’ll try and find a way to avoid hard coding hostnames but if all fails I’ll do that. In any case it will be published as v0.1.1 👍

If it's not too much trouble, could you also add too? I haven't included it there yet, but I plan to.

I'll try my script there, if it has the same issue sure. But first I want to check if there's a way for me to detect the history issue beforehand and apply the fallback without having to add a list of domains in the script. Looking at it now.

@inertia good news, I found a way to avoid that error without the need to hardcode domain names.
Will publish it in the morning after some tests.

There seems to be a CORS issue that only the spaminator/hivewatchers team can resolve (unless we proxy those requests to remove the Origin header automatically added by browsers):


I reached out to them here and on discord.

@spaminator @guiltyparties @logic @hivewatchers @hivewatcher

Would you please be able to add to the response header "Access-Control-Allow-Origin" set to "*" in order to allow requests from the various frontends without having to proxy them to remove the Origin header that is causing the CORS issues?


I'm not involved with spaminator

for you

Thank you for this @keys-defender.

  • I will work on this tomorrow 😊👍

    Posted via D.Buzz

You may want to wait for v 2.0 that I'll publish early next week


  • Thank you and please tag me.

    Posted via D.Buzz

Can we ask for Access-Control-Allow-Origin: * to be set on*/avatar/small, should be ok to allow these images to be used and peertube for one is trying to do this on my instance.

Maybe @quochuy can help

This is for the image server not the condenser. @blocktrades?

Images can be used as is without that setting (using the img src=) and I don't think they should be used differently.

Is this not a phishing scam itself? Of course, the hackers are going to say they will defend you from hacking.

lol what? 🤓

My script consumes other blacklists and automatically prevents users from opening compromised or unsafe domains.
My code provided in the github in this article is OPEN SOURCE, meaning that devs that want to integrate it into their Hive frontend can review it, copy it and use it as they please.