28. Feb 2022Frontend

What happened to Faker.js and how to secure your projects

The golden rule when installing external javascript modules is that we should prefer popular packages that are frequently updated. The Faker.js library has met all this, and tens of thousands of developers have used it to generate random data such as people's names or company names as a useful tool, during development or tests.

Matej DugovičBackend Developer

However, its developer Marak surprised everyone on January 5, when he released a version with completely erased code in the last update. He placed an endless loop in another colors.js library. It's not entirely clear why Marak did it.

When Github and NPM blocked his access to the projects, Marak wrote on Twitter that everyone made programming mistakes from time to time. However, it wasn't a mistake, it was an intention.

After the release of the version, Marak rewrote the comments on the Githube and published links to unrelated posts. This is not the first time the author has decided to remove his work, although thousands of other projects have depended on it.

💡 In the most famous incident in 2016, the developer of Koçul , removed from the registry, among other things, the left-pad module, which was used by many libraries - for example, React.

At that time, the NPM people restored the module and prevented the future deleting from anything that someone else was already using in another project.

Nevertheless, Marak managed to disable projects such as the AWS Cloud Development Kit, which used the colors.js module.

Versions of libraries and faker for JavaScript continue under a different management.

If you stick to at least a few of our basic tips, you can minimize the risk that similar situations will affect you unpleasantly.

Updates

Managing modules and updating dependencies is one of the few things you should do manually, even if it's more annoying.

This should be kept in mind especially for module registries such as NPM for JavaScript, which offer a degree of automation by default. Then any of the highest compatible versions can be installed.

In reality, however, a minor update that brings the new bug will break your code and will not be executable. The surest way to avoid an unwanted upgrade of a module is to use only the version number in the package.json file and increase it manually. Each time a new module is added, it is necessary to delete the "^" or install a specific version of the module.

🔒 Safe way to wite: "typescript": "4.3.4"
⚠️ More risky way: "typescript": "^4.3.4"

In this case it's ok to install version between 4.3.4 and 5.0.0.

Mostly you will encounter a version with "^" or only with version number, but npm supports more variations.

Ideally is best to update modules one by one, it's easier to identify possible problem. Known and wanted problems with compatibility should be already noted in update changelog. Less often, problems can also be caused by internal module dependencies that contain an error or conflict with another package. It is therefore important to use package-lock.json, which also fixes versions of internal dependencies.

Do I need to check every change in commits? 

The aforementioned problems with the faker and left-pad modules were devastating, but easily and quickly detectable. However, if it is a targeted attack by hackers who take access to the release of new versions of the module, they will certainly want to draw as little attention to themselves as possible. Several modules (eg Coa) have been issued by malicious attackers in this way.

Problems can usually be detected during commit checks (if the version is automatically published via CI pipeline), but in practice only large companies audit updates in this way. In addition, in the case of direct access to the npm registry, an attacker can publish the attack version directly from his computer (but simple protection through two-factor authorization will help here).

It is also worth remembering the "harmless" prank of the developer for the UI library for React Ant Design. Although the library is profiled for companies and corporations, one of the authors dared to add, without warning, an update that added a snowfall effect to the button components at Christmas. After criticizing the surprised developers, the author apologized and removed the unwanted feature.

How to choose a library

When choosing a module it's good to compare libraries from multiple developers.

The ideal candidate could look like this:

  • It is used by hundreds, thousands of other programmers. It has worked out bugs that have manifested itself in normal operation on various systems and should therefore be more stable and safer.
  • It's regularly updated. Although some products are functionally complete, they may have dependencies with security vulnerabilities that need to be updated, for example.
  • It is run by a larger community or company and not by one person. On the one hand, development and bug fixes are faster, but there is less risk that you will have to look for an alternative if the developer stops taking care of the project. Or sabotage it like Marak
  • It has a benevolent license (eg. MIT), which attracts more users and companies. You will also be able to modify the code to suit your needs.

Sometimes, of course, it's worth breaking these rules if the new library is faster, smaller, or easier to use, or behaves exactly the way you need it. But the code should at least be easy to maintain if you have to fix something yourself later.

Matej DugovičBackend Developer