What are memory leaks Tutorial & examples Snyk Learn

Todo

Learn about memory leaks, and how to mitigate and remediate the vulnerability with real-world examples from security experts.


What is a memory leak?

Memory leaks are a common source of performance issues and instability in JavaScript applications. A memory leak occurs when a Node.js program fails to release memory that it no longer needs, causing the program to consume more and more memory over time. This can lead to poor performance, slow response times, and ultimately, cause the application and other applications to crash.

When an application does not need a memory block anymore, it should release it back to the OS. In the case of a memory leak, the garbage collector never collects the block and it stays on the heap.

There are several common causes of memory leaks in Node.js, such as global variables, multiple references, and incorrect use of closures and timers.

About this lesson

In this lesson, you will learn about vulnerabilities stemming from a memory leak and how to protect your applications against them. We will step into the shoes of a junior pentester, Jacob, who accidentally DoSed (Denial of Service) their client’s website when performing tests for a different type of vulnerability.

FUN FACT

Garbage collector

Node.js uses a “garbage collector” to automatically manage memory and prevent memory leaks. However, if an application keeps references to objects, those will not be cleared by the garbage collector.

Jacob, a junior pentester for a cyber security firm in the south, is doing a pentest for SocialsCorp. SocialsCorp is a new social media platform where users have their own profile pages.

Jacob starts with trying to test the application for a common vulnerability type; IDOR (Insecure Direct Object Reference).

Finding a memory leak

Setting the stage

Jacob's testing the `user/{id}` endpoint where he tries to access the details of other users by incrementing the ID value. Let's see what happens.

memory-leaks-start.svg

FUN FACT

Third-party libraries

Memory leaks do not always exist in the code of the company itself. It can also be caused by third-party libraries, or by incorrect use of third-party libraries.

Let’s break down what happened in the story above. Jacob was sending requests to the user endpoint with different user ID’s. After a handful of requests, the server got really slow and eventually crashed.

The backend code of the user endpoint was not releasing memory after use, causing allocated memory to be never released and overall memory usage to climb. The backend code of the user endpoint is the following:

The endpoint fetches the user from the database, then checks if the current logged-in user is allowed to view that user, and if so, returns the user object.

There are a few flaws here:

  1. The requested user is fetched from the database (if the users dictionary did not contain the user), regardless of the permissions that the authenticated user has.
  2. The retrieved users are stored in a global variable that will keep growing larger as more users are fetched.

Each time a user is requested, the users dictionary will grow. Jacob triggered an out of memory crash (a memory leak) by requesting a lot of different users in a short period of time. Because the user data can also contain profile pictures and other large data properties, the users dictionary got to a point where it was consuming all memory.

What is the impact of a memory leak?

A memory leak in a Node.js application can have serious consequences for its performance and stability. If the process continues to consume more and more memory over time, it can eventually result in an out-of-memory error, causing the process to crash. Just like with the application Jacob was pentesting. Not only can the application that contains the leak crash but other applications might panic too if they are not able to allocate new memory.

Additionally, memory leaks can lead to slower performance as the process spends more time managing and garbage collecting the increasing amount of memory it is using. This leads to decreased responsiveness and a poor user experience.

To migrate a memory leak in a Node.js application, you can follow these steps:

To migrate the memory leak in the users endpoint code:

A good caching library in Node.js is cache-manager. You can find more about this package, including a security scan and health check, at https://snyk.io/advisor/npm-package/cache-manager

Implementing the cache-manager package into the users endpoint code, and performing the permissions check first, will look like something this:

FUN FACT

Built-in profiler

Node.js has a built-in profiler that can be used to detect memory leaks and profile the performance of your application. To use the profiler, you can use the --prof flag, which communicates with the V8 profiler to gather information from functions and store it in a file.

Keep learning

Congratulations

Now you know more about memory leaks and how to prevent them! We hope that you will apply this knowledge to make your applications safer. We'd really appreciate it if you could take a minute to rate how valuable this lesson was for you and provide feedback to help us improve! Also, make sure to check out our lessons on other common vulnerabilities.