Recently, we employed the services of a contractor on Upwork to help us build our private, decentralised CAPTCHA service, Procaptcha. The contractor seemed nice enough via chat and he agreed to a very reasonable rate. His profile showed him as being a Ukrainian national, which was a plus for us as we wanted to support the Ukrainian tech industry. Let's refer to the contractor as Artur from here on in (not his real name).
We'll now highlight a series of mistakes we made that led to Artur blackmailing us. We hope that by sharing our story, we can help others avoid the same pitfalls. And hopefully not make them again ourselves!
Initially, things got off to a slow start. Despite the ad being for a TypeScript developer, it seemed Artur had mostly worked with PHP before and was unfamiliar with the monorepo structure we use at Prosopo. We spent a lot of time helping him get up to speed with our tech stack, which was fine as we expected this to be the case. We were happy to help him learn and grow.
Our first mistake was failing to check Artur's technical capabilities thoroughly enough. We should have asked for proof of his crendentials and maybe for him to complete a small test task before hiring him. We were in a rush and didn't do this.
Artur successfully completed some smaller UX tasks and we were happy with the results. We gave him a larger task involving a number of our services. A new feature was to be implemented and Cypress tests needed to be written to ensure it was working properly. Artur suddenly started to cost us a lot more time in productivity than he was giving back in output. We were patient, but it was clear that Artur was struggling with the task. We weren't able to speed up his progress as he refused to chat via voice call, claiming his spoken English was not good enough. We're fully remote so this was a problem.
Our second mistake, was not conducting a thorough interview process. We should have at least conducted a spoken interview but our previous experience with Upwork has suggested this isn't always necessary.
Artur had now been working with us for a month and we were not making the progress we had hoped for. During a meeting on funding, we decided we couldn't justify the cost of Artur's time any longer. We decided to terminate the contract with him. This happened to coincide with Artur being away for 2 weeks visiting his whom were unwell. Before he left for this trip, he had asked for a week's pay in advance, which we refused. He then enthusiastically stated his desire to continue working for us, saying he would work for free if necessary. It sounded like he knew he wasn't being productive and was trying to make up for it.
Our third mistake was not being transparent with Artur about his performance. His productivity issues and reluctance to use voice communication should have been addressed sooner. Transparent communication might have improved his performance or led to an earlier, more amicable termination of his contract.
A week into Artur's trip, we informed him that we would be terminating the contract. When he returned, he was very upset and asked if we would reconsider if he halved his hourly rate. We did consider it, but ultimately refused his offer as he was detracting so much time from the team that it wasn't worth it.
We thought no more of it and continued on as usual. After all, Artur is a contractor and we had no obligation to keep him on if he wasn't performing. However, a few days later we received an email from Artur after removing him from our team Slack channels. He had taken a number of our private repositories and was threatening to release them to our competitors.
Strangely, he used our contact form instead of our email addresses. On a more serious note, we didn't ask Artur to fill in an Non-Disclosure Agreement (NDA) before starting work with us. We should have had an NDA in place before starting work with Artur. This would have given us legal recourse to take action against him.
We were in a panic. We didn't know what to do. Although the code Artur was ransoming was not very valuable in itself, the repo did contain some SSH keys and sensitive account information. This resulted in a frantic afternoon of key cycling and brings us to our fifth pitfall: always use a secrets manager and don't commit secrets to code - even in private repositories!
We asked Artur why he was behaving this way:
He then went off on a rant but revealed something interesting. His email return name was not Artur, but a different name with the initials "RH".
At this point we engaged our legal counsel, Kenneth MacDonald (M.B) who drafted up a cease and desist letter. We sent it to Artur. We had also planned to report him to Upwork, but his profile had already been deleted. Go figure.
Artur replied fairly quickly and continued to threaten us. We then got lighthearted with him and asked him to send all of our source code to our competitors. As we mentioned, we were only really concerned about the release of our secrets as the majority of our code is open source!
It seems that our friend Artur was bluffing or confused by our clever use of emoji. We haven't heard from him since.
Early on, Artur had recommended a friend, who engaged with us on our Discord. They joined and said, "Hello", and pretty much nothing else. A month later, after the blackmail incident, the account mysteriously came alive.
The account that joined our Discord has a GitHub account with hundreds of followers and a number of repositories with about one commit each. Each of the accounts following it has a similar pattern. Although we can't say for certain, it seems likely that these are GitHub accounts Artur's been using to scam other companies, presumably via other fake Upwork profiles.
If you're interested in more details about the scam network we uncovered, please get in touch.