Security for Developers: Vulnerability Management
Start with a simple process and don't over-optimize
I’m having my first sale in a while. Thanks again for all the support!
I’ve also un-paywalled an article as part of the promotion. Hope you enjoy!
I’m continuing my series on helping developers do security. The idea is that these posts make it easy for developers to get started on security before they hire a dedicated security person or to just improve their overall security skills.
I’ve written about a few other topics in the past, like access control, basic web security, and threat modeling. Today, I’m going to talk about vulnerability management.
What is vulnerability management?
Vulnerability management is the process of identifying, assessing, remediating, and reporting on vulnerabilities. This is pretty straightforward. The only nuance is that this process is continuous, so all four of those actions should always be happening.
Not to be too pedantic, but what is a vulnerability? According to ISO 27002, a security standard, a vulnerability is “a weakness of an asset or group of assets that can be exploited by one or more threats.” It might seem simple, but the hardest part of vulnerability management is figuring out the vulnerability.
Why do you need vulnerability management? It’s good practice, and as a company’s infrastructure and codebase become more complex, there’s a more threat surface for vulnerabilities to both appear and be exploited. But, earlier on, there’s not that much complexity or code. The forcing function is typically compliance, such as SOC2, ISO, or HITRUST certification.
How do I get started?
There’s a bunch of resources online if you Google “vulnerability management,” if you want to read more. Usually, they are overkill if you’re looking to do the basics. Some useful resources are the Common Vulnerability Scoring System (CVSS), which describes how severe a vulnerability is, and the National Vulnerability Database (NVD). I’ll talk more about this later, but the CVSS and severity scores are just guidance scores and can vary depending on any mitigations you have in your environment.
Of course, it doesn’t make sense to regularly check the NVD for vulnerabilities, find them in the code, and remediate them. Luckily, there are plenty of tools in this space. Some popular open-source/free ones are Snyk and Semgrep. They have paid versions that add additional features that aid in more complex environments, but the free versions of these tools are sufficient to just start scanning a basic codebase. Similarly, GitHub comes with a free tool called Dependabot, which is limited to dependency scanning, i.e. finding vulnerabilities in dependencies. However, that’s likely sufficient to start.
Speaking of types of vulnerabilities, there are two types that people generally worry about. The first and most common are dependency vulnerabilities. Nowadays, rarely do people write code from scratch, especially with the increased use of higher-level languages like Python. Your code will likely import libraries and use them, and most of the vulnerabilities come from this. That’s what most of the free software scans.
The second type is vulnerable code. This is what typically happens that leads to dependency vulnerabilities, i.e. vulnerable code in a library triggers the first type of vulnerability. This could be the use of a function that leads to some memory overflow or exploitable string. Snyk and Semgrep have tooling called static application security testing (SAST) that can help detect it, but that’s highly context dependent. Usually, at a mature stage, companies have a variety of techniques to help find vulnerable code, such as pentesting, bug bounties, etc.
For the rest of the blog, let’s focus on the first type of vulnerability, dependency vulnerabilities, because it’s the most common one.
I found a vulnerability. So now what?
Some of these tools are noisy and will spit out vulnerabilities. Now, the tool has found one, what do you do?
First, before choosing whether to fix an issue as opposed to backlogging it, you have to decide your risk tolerance, i.e. do you want to fix all vulnerabilities or only certain types? Do you want to start with the critical ones and then move onto the high ones? A good place to start is to fix the ones that are exploitable (whether or not they can be exploited in your environment). Next, I would eliminate all the ones that don’t have fixes. Yes, there are vulnerabilities without fixes, typically because they are easily mitigable or not a major issue to start with. As you have more resources, you can decide to fix more types of vulnerabilities, e.g. moving onto the fixable medium ones, but vulnerability management is about risk management.
I won’t discuss the best way to fix these vulnerabilities because it’s somewhat of a controversial topic. Most traditional and operational security teams have a whole process to triage and manage vulnerability remediations with SLAs. My belief, at least for a startup, is that whoever has the most context should fix it, and security shouldn’t shy away from fixing it if either they have the most context or there’s not a clear owner. But, a lot of people have strong opinions about this, but I think it’s the most practical way.
There are two ways a vulnerability might come up. First, someone accidentally uses a vulnerable library in the code, and a scan picks it up. Ideally, in this case, you have scanning in CI/CD to prevent that. If you don’t and you pick it up later, you just follow the process above to remediate it. Second, an engineer uses a library, and later on, someone discovers a vulnerability in that library. This is somewhat common where at the time of code writing, the code isn’t vulnerable, but a discovery makes flags it. The process should be the same, but the urgency depends on how risky the vulnerability is and your risk tolerance.
Honestly, that’s it. That’s a basic vulnerability management process. There are ways to make it more complex. For example, you can have a dependency repository to ensure that you know what dependencies people are using and restrict to certain versions. This makes it easy to have a software bill of materials (SBOM), which is helpful in more complex environments. You can use the tooling more to operationalize the finding and resolving of vulnerabilities. Either way, the fundamentals are the same is that you need to understand what types of vulnerabilities are worth fixing and on what time scale.
At the heart of it, vulnerability management is just a process. There’s not complex engineering involved, and most of the complexity comes from the remediation phase, which is only a small part of the process. It comes down to risk management and how much your company wants to invest in reducing that risk.