How Do You Keep Your JavaScript Dependencies Up-to-date?

Share this article

How Do You Keep Your JavaScript Dependencies Up-to-date?

Key Takeaways

  • Keeping JavaScript dependencies updated is crucial for maintaining the security of your applications. This is because outdated libraries can introduce vulnerabilities into your code base, which could potentially be exploited by online criminals.
  • Tools and services like npm-check, Greenkeeper.io, and Snyk can help developers keep track of outdated, incorrect, and unused dependencies, automating the process of keeping libraries up-to-date, especially as an application grows in size and complexity.
  • Implementing subresource integrity (SRI) can mitigate the risk posed by third-party scripts. SRI allows the browser to verify that resources hosted on third-party servers haven’t been tampered with, ensuring the integrity of the content being fetched.

This is the editorial from our latest JavaScript newsletter, you can subscribe here.

JavaScript Dependencies — Skull of death

Recently, security researchers analyzed 133,000 websites for outdated JavaScript libraries. Their findings, presented in a whitepaper, Thou Shalt Not Depend on Me: Analysing the Use of Outdated JavaScript Libraries on the Web, do not make for happy reading. Of the websites analyzed, 37% loaded insecure JavaScript, either directly or via a third-party service, such as advertisers.

This made me sit up and take notice. The libraries these researchers were checking for were 72 of the most popular open-source projects out there — libraries like Angular and jQuery that we all use every day. I’d never really stopped to think whether an outdated version of jQuery could present a serious security threat. And I had (almost) certainly never gone back to update an old version of jQuery on a website I had made. Was this something I should have been doing?

My Career as a L33t H4x0r

So, now I was curious and decided to see if I could use an outdated version of jQuery to hack one of my own pages. I started off searching for “jQuery security vulnerabilities” and pretty soon stumbled across this issue on jQuery’s GitHub repo. People were pointing to this as a potential cross-site scripting vulnerability which meant that an attacker could execute arbitrary code at the request’s origin. That sounded promising …

The issue was easy enough to reproduce — the problem was that jQuery was executing every text/javascript response it received when performing a $.get() request — but that was as far as my excitement went. As one of the jQuery maintainers pointed out in the thread, this “exploit” was similar to including third party code via <script> tags. This wasn’t likely to bring my website to its knees and was hardly the stuff hacking movies are made of.

Take 2: A Bit of Session Hijacking

Not wanting to be deterred, I imagined what I would do if the exploit had worked and I could execute arbitrary code on a user’s computer. One thing we are often warned against is session hijacking where a malicious script can manipulate a user’s cookies to gain unauthorized access to information or services they are logged into. So, I thought I’d try my hand at that.

I started off by attempting to print out the cookies of a service I was logged into (a simple Rails app which used the Devise gem for authentication). I opened the browser console and entered document.cookie expecting to see my session token returned, which I could ajax off to a remote server for all kinds of nefarious purposes … But unfortunately, this command just returned an empty string. Closer inspection revealed that Devise uses HTTPOnly cookies, that are not accessible via JavaScript to prevent exactly this kind of attack. Curses! Hacking was proving to be considerably harder than I hoped.

It’s a Jungle out There

Ok, so it turns out I’m not the world’s best hacker, but joking aside, it is actually a jungle out there! Browser security has come on in leaps and bounds in the past years (HTTPOnly cookies being an example in point), but online criminals are always a step or two ahead. The list of possible attacks is seemingly endless and as you build more complicated applications, the libraries you use will (unwittingly) introduce vulnerabilities into your code base. Keeping these libraries patched to the best of your ability, or at least being aware that some are potentially insecure, has to make sense, right?

Our original outdated version of jQuery shouldn’t prove too challenging to update, but what about when an application starts to grow? Luckily there are a few tools and services to help you. For example the npm-check package does what it says on the tin and will check for outdated, incorrect, and unused dependencies. It will also kindly provide a link to a package’s documentation so you can decide if you want the update. There are also services such as Greenkeeper.io and Snyk which automate the process, but these are starting to stray into Node territory.

One for the Road

There’s one more tip that I’d like to share which goes some way to mitigating the danger posed by third party scripts. This is to verify third-party content using subresource integrity (SRI). You might have come across this if you’ve attempted to include jQuery from the jQuery CDN lately. You’ll see something like:

<script 
  src="https://code.jquery.com/jquery-3.2.1.min.js"
  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" 
  crossorigin="anonymous"></script>

What’s new here is the integrity attribute on the <script> tag which can be used to specify a base64-encoded cryptographic hash of the resource you’re asking the browser to fetch. This effectively allows the browser to ensure that resources hosted on third-party servers have not been tampered with.

Using SRI is now a recommended best-practice. You can use the SRI Hash Generator to create hashes of your own.

Conclusion

Keeping your application’s JavaScript dependencies up-to-date is just one small piece of a much larger security puzzle. For small projects this is probably doesn’t represent much effort, but as a project begins to grow, so to does the time and effort involved in ensuring that all of the project’s dependencies are adequately patched. I think this is an important topic, but one which receives far too little press — we all tend to fire and forget when it comes to installing JavaScript libraries and modules.

But what do you think? How much importance do you put on keeping things up-to-date? Would your site be one of the 37% loading insecure JavaScript? How much of a problem is this for our industry as a whole? Let me know in the comments below.

Frequently Asked Questions (FAQs) about JavaScript Dependencies

What are JavaScript dependencies?

JavaScript dependencies are external pieces of code or libraries that your JavaScript project relies on to function correctly. They can include frameworks like React or Angular, utility libraries like Lodash or Moment, or even smaller, single-purpose modules. These dependencies are usually managed and installed using package managers like npm or Yarn.

Why is it important to keep JavaScript dependencies up to date?

Keeping your JavaScript dependencies up to date is crucial for several reasons. Firstly, updates often include important security patches that can protect your project from vulnerabilities. Secondly, updates can bring new features or improvements that can enhance the functionality of your project. Lastly, staying up to date can help ensure compatibility with other updated dependencies or technologies.

How can I check if my JavaScript dependencies are up to date?

You can use tools like npm-check-updates or Yarn’s upgrade-interactive command to check if your JavaScript dependencies are up to date. These tools compare the versions of your installed dependencies against the latest versions available on the npm registry and provide a list of outdated dependencies.

How can I update my JavaScript dependencies?

You can update your JavaScript dependencies using npm or Yarn. For npm, you can use the command ‘npm update’ to update all dependencies, or ‘npm update ‘ to update a specific package. For Yarn, you can use the command ‘yarn upgrade’ to update all dependencies, or ‘yarn upgrade ‘ to update a specific package.

What is semantic versioning in JavaScript dependencies?

Semantic versioning is a versioning scheme for software that aims to convey meaning about the underlying changes with each new release. In JavaScript dependencies, a version number is composed of three parts: major, minor, and patch (e.g., 1.2.3). A major version change indicates that there are incompatible API changes, a minor version change indicates that new features have been added in a backwards-compatible manner, and a patch version change indicates backwards-compatible bug fixes.

What is a package.json file in JavaScript?

The package.json file is a crucial file in any JavaScript project. It contains metadata about the project, such as its name, version, and description. More importantly, it lists the project’s dependencies and their respective versions. This file is used by npm or Yarn to determine which dependencies to install for your project.

What is the difference between dependencies and devDependencies in package.json?

In a package.json file, dependencies are libraries that your project needs to run, while devDependencies are libraries needed for developing the project, such as testing frameworks or bundlers. When you install your project in a production environment, only the dependencies are installed, not the devDependencies.

What is a lock file in JavaScript?

A lock file, such as package-lock.json or yarn.lock, is automatically generated by npm or Yarn when you install your dependencies. This file locks down the exact versions of your dependencies that your project is using, ensuring that you and your team are all using the same versions, and that the same versions are used in production.

How can I handle breaking changes in JavaScript dependencies?

When a dependency introduces a breaking change, you can handle it by carefully reading the release notes or changelog of the dependency to understand what has changed. Then, you can update your code to accommodate the changes. It’s also a good practice to have a comprehensive suite of tests for your project, so you can quickly identify any issues caused by the update.

What are peer dependencies in JavaScript?

Peer dependencies are a special type of dependencies that are expected to be provided by the environment in which your project is running. They are often used for plugins that need to use a specific version of a library. For example, a React plugin might specify React as a peer dependency, indicating that it should be used with a specific version of React that is already installed in your project.

James HibbardJames Hibbard
View Author

Network admin, freelance web developer and editor at SitePoint.

dependency managementeditorialjamesh
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week