Ever seen “CVE-” codes flash by during a software install and wondered what they meant? You’re not the only one; we’ve all been there. These codes are important cybersecurity distress signals. I’ll guide you through the anatomy of a CVE identifier, explain its structure, and explore concepts like ‘transitive dependencies’ and the best practices for patching vulnerabilities.
What is a CVE?
Vulnerabilities used to have names that were specific to the bug, like “IIS path traversal”, but as vulnerabilities stacked over decades, a standardized identifier became necessary.
A Common Vulnerabilities and Exposures (CVE) identifier provides a standardized name for publicly known, identified cybersecurity flaws. This common vernacular enables security professionals and vendors to quickly and accurately communicate about specific weaknesses. Identifying CVEs in software is essential – especially in environments with many external components – as it allows security teams to prioritize patching, assess risk, and rapidly fix defects before exploitation, thus protecting data and system availability.
You can think of a CVE as a tracking number, just like if you were to order a package from your favorite retailer. It is a way to keep track of the bug(s) and stay abreast of what versions of a package were affected by the vulnerability.
For a complete overview of best practices, you can learn more about CVE patching in our in-depth guide.
The Structure of a CVE
A CVE looks like this: ‘CVE-2025-1111‘ – the prefix CVE, followed by the year the flaw was discovered, followed by a unique identifier.
This number is assigned by the MITRE Corporation and a global network of over 490 CNAs. These CNAs (CVE Numbering Authorities) include IT vendors such as Microsoft, Red Hat, and Oracle, along with various organizations and security researchers.
The National Vulnerability Database (NVD) is tasked with enriching each CVE once it has been published to the CVE list. In practice, this means there is a handoff between MITRE and the NVD, which then enriches the CVE with additional metadata. There is a process that it goes through once this handoff is complete. According to NIST, the process includes:
- Reviewing the material that is provided with the CVE.
- A CWE (Common Weakness Enumeration) ID is assigned to the vulnerability that categorizes it.
- Exploitability (by CVSS v3.1 or v4.0 metrics) and impact metrics are assigned.
- A CPE or Common Platform Enumerator statement is associated with the vulnerability.
- Finally, a senior analyst performs a QA check before the enriched data is published.
Once the CVE is published, there may be more maintenance moving forward. There could be modifications, reference material added, descriptions updated, etc.
Understanding the Vulnerability
When you run npm audit or just install a package within your project, you may see output like: 7 high severity vulnerabilities. You might be asking yourself, “What are those and what do they look like?” The initial output doesn’t list the CVEs; instead, it lists the affected packages and their versions. Here is an example of the npm audit output when installing Angular v18 (the picture gets noisier on older releases like Angular 16, where dependency rot has had over a year to pile up):
rollup 4.0.0 - 4.58.0 Severity: high Rollup 4 has Arbitrary File Write via Path Traversal - https://github.com/advisories/GHSA-mw96-cpmx-2vgc fix available via `npm audit fix --force` Will install @angular-devkit/build-angular@19.2.22, which is a breaking change node_modules/rollup @angular/build 18.1.0-next.0 - 19.2.21 || 20.0.0-next.0 - 20.2.0-rc.1 || 20.3.4 - 20.3.17 Depends on vulnerable versions of rollup node_modules/@angular/build @angular-devkit/build-angular * Depends on vulnerable versions of @angular/build Depends on vulnerable versions of copy-webpack-plugin node_modules/@angular-devkit/build-angular
What this means is that the rollup package was installed as a transitive dependency. The versions affected are 4.0.0 – 4.58.0. Those versions have a high-severity security vulnerability. The vulnerability is called the “Arbitrary File Write via Path Traversal” flaw. What this means is that a malicious actor can create input that tricks rollup into writing a file to locations you didn’t intend to write to. This is a classic example of a software supply chain vulnerability. You installed a package, but rollup came along for the ride, and you didn’t intentionally install it.
@angular-devkit/build-angular └── @angular/build (vulnerable versions) └── rollup (4.0.0 - 4.58.0) ← the vulnerable package
Fixing Flaws
If we keep working off the rollup example, there are a couple of different ways to fix this vulnerability if you aren’t actively writing CVE fixes as a security application developer. You could run npm audit fix –force, and that could fix the problem, but that approach comes with its own set of trade-offs..
If you run that command, it will also upgrade @angular-devkit/build-angular to version 19.2.22. That version is flagged as a breaking change and could affect build configurations and APIs. It may require changes to the code later down the line and who has time for that?
Some things you can do to see how to fix it:
- Check your version of Angular to assess how big the jump would be to the new version.
- Reference the changelog of the @angular-devkit/build-angular version to the upgraded version.
- Create a new branch and run the fix in that, never in main.
- Acknowledge and defer the change if it is too risky.
Overrides
Using an override is a temporary fix that can move you forward, but it also has its risks. It can force a patched, specific version of the rollup package without having to resort to the breaking upgrade of @angular-devkit/build-angular.
You can add the patched version in your package.json like below. The version in the example json is the latest patched version as of February 2026.
{ "overrides": { "rollup": "^4.59.0" } }
Make sure that you run npm install to install the patched version and double-check that it was also installed by running npm audit. You should see that the vulnerability is gone.
The reason this solution works is that the overrides field is telling npm, “no matter what, no excuses, install this package”. It will bypass the transitive dependency tree entirely using the overrides.
Overrides are a good approach when:
- You really need to ship and are blocked by the breaking upgrade
- Since the vulnerability is in a build tool and not a production tool, the risk is lower
- The build has been tested, and it’s been confirmed that nothing is broken
There are better ways to approach this since the overrides field is just temporary. You can accept the breaking change as long as you test it in a branch and the tests pass. If there are no issues and it has been reviewed, move forward. If there is a patch that exists and it is non-breaking, use that. Check the changelog for major/minor patches that won’t break the build. One last thing to do is evaluate the actual risk.
As stated above, rollup is a build tool, not a production-level tool, so the risk is lower. It typically doesn’t run in production environments. Using overrides can create a false sense of security at the end of the day. You will stop getting warnings from npm audit, but you are also introducing untested changes into your project/build.
The takeaway is simple: if you can accept the breaking change, do it. If you can’t, then use overrides.

