From d077d60f9a4d2e0f4e9c5132c8c1d27336c4bdc5 Mon Sep 17 00:00:00 2001 From: Juliano Souza Date: Sun, 28 Jun 2026 13:23:44 -0300 Subject: [PATCH 1/3] docs: document direct and transitive dependency versions --- website/docs/how-remediation-works.mdx | 62 ++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/website/docs/how-remediation-works.mdx b/website/docs/how-remediation-works.mdx index a0dd0915..7d5522d5 100644 --- a/website/docs/how-remediation-works.mdx +++ b/website/docs/how-remediation-works.mdx @@ -473,6 +473,68 @@ The same package name appearing twice in your scan output is not a duplicate — --- +## Direct and transitive versions of the same package + +The same package name can appear as both a direct dependency and a transitive dependency when different versions are installed. These are independent installs, and each installed version must be classified independently. + +A version is direct only when that specific installed version matches the dependency declared by the project. Another installed version with the same package name can still be transitive when it arrives through unrelated parent packages. + +For example, a project may declare `uuid@14.0.0` directly, while packages such as `@compodoc/live-server`, `nyc`, and `codecov` introduce a vulnerable `uuid@8.3.2` transitively: + +```mermaid +flowchart TD + P(["Your project"]) + P --> D["uuid@14.0.0\ndirect dependency"] + P --> L["@compodoc/live-server\nparent package"] + P --> N["nyc\nparent package"] + P --> C["codecov\nparent package"] + L --> V["uuid@8.3.2\ntransitive and vulnerable"] + N --> V + C --> V + + style P fill:#1e3a5f,color:#93c5fd,stroke:#3b82f6,padding:12px + style D fill:#14532d,color:#86efac,stroke:#22c55e,padding:12px + style L fill:#1e293b,color:#cbd5e1,stroke:#475569,padding:12px + style N fill:#1e293b,color:#cbd5e1,stroke:#475569,padding:12px + style C fill:#1e293b,color:#cbd5e1,stroke:#475569,padding:12px + style V fill:#7f1d1d,color:#fca5a5,stroke:#ef4444,padding:12px +``` + +Running `npm install uuid@9.0.0` is the wrong fix in this scenario. It can install a third version of `uuid` and conflict with the already declared `uuid@14.0.0`, while the vulnerable transitive `uuid@8.3.2` may still remain in the lockfile. + +Because the vulnerable `uuid@8.3.2` is controlled by the parent package or dependency path that introduced it, remediation should target that parent instead of the unrelated direct `uuid@14.0.0` dependency. + +If the parent's declared range already allows a non-vulnerable version, refreshing the lockfile may resolve the finding. If it does not, the parent package may need to be upgraded to a version with a compatible, non-vulnerable dependency range. + +**Generated command:** + + + + ```bash + npm install nyc@18.0.0 + ``` + + + ```bash + pnpm add nyc@18.0.0 + ``` + + + ```bash + yarn add nyc@18.0.0 + ``` + + + ```bash + bun add nyc@18.0.0 + ``` + + + +The generated command targets a parent package that controls the vulnerable transitive `uuid@8.3.2`, not the unrelated direct `uuid@14.0.0` dependency. The exact parent and version depend on the dependency path CVE Lite CLI can verify. + +--- + ## Offline mode When running with `--offline` or `--offline-db`, CVE Lite CLI cannot make registry calls. This affects transitive remediation: From 4ab8704b65f11089da26d83fb44fb85b1b64bdd2 Mon Sep 17 00:00:00 2001 From: Juliano Souza Date: Tue, 30 Jun 2026 16:31:07 -0300 Subject: [PATCH 2/3] docs: clarify selected parent upgrade path --- website/docs/how-remediation-works.mdx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/website/docs/how-remediation-works.mdx b/website/docs/how-remediation-works.mdx index 7d5522d5..4c11f92d 100644 --- a/website/docs/how-remediation-works.mdx +++ b/website/docs/how-remediation-works.mdx @@ -479,12 +479,12 @@ The same package name can appear as both a direct dependency and a transitive de A version is direct only when that specific installed version matches the dependency declared by the project. Another installed version with the same package name can still be transitive when it arrives through unrelated parent packages. -For example, a project may declare `uuid@14.0.0` directly, while packages such as `@compodoc/live-server`, `nyc`, and `codecov` introduce a vulnerable `uuid@8.3.2` transitively: +For example, a project may declare `uuid@14.0.1` directly, while packages such as `@compodoc/live-server`, `nyc`, and `codecov` introduce a vulnerable `uuid@8.3.2` transitively: ```mermaid flowchart TD P(["Your project"]) - P --> D["uuid@14.0.0\ndirect dependency"] + P --> D["uuid@14.0.1\ndirect dependency"] P --> L["@compodoc/live-server\nparent package"] P --> N["nyc\nparent package"] P --> C["codecov\nparent package"] @@ -500,12 +500,14 @@ flowchart TD style V fill:#7f1d1d,color:#fca5a5,stroke:#ef4444,padding:12px ``` -Running `npm install uuid@9.0.0` is the wrong fix in this scenario. It can install a third version of `uuid` and conflict with the already declared `uuid@14.0.0`, while the vulnerable transitive `uuid@8.3.2` may still remain in the lockfile. +Running `npm install uuid@9.0.0` is the wrong fix in this scenario. It can install a third version of `uuid` and conflict with the already declared `uuid@14.0.1`, while the vulnerable transitive `uuid@8.3.2` may still remain in the lockfile. -Because the vulnerable `uuid@8.3.2` is controlled by the parent package or dependency path that introduced it, remediation should target that parent instead of the unrelated direct `uuid@14.0.0` dependency. +Because the vulnerable `uuid@8.3.2` is controlled by the parent package or dependency path that introduced it, remediation should target that parent instead of the unrelated direct `uuid@14.0.1` dependency. If the parent's declared range already allows a non-vulnerable version, refreshing the lockfile may resolve the finding. If it does not, the parent package may need to be upgraded to a version with a compatible, non-vulnerable dependency range. +When multiple parent packages introduce the same vulnerable transitive version, CVE Lite CLI selects the most actionable upgrade path based on the dependency paths it resolves in your lockfile. In this example, the generated command targets `nyc` as the selected parent upgrade path. + **Generated command:** @@ -531,10 +533,11 @@ If the parent's declared range already allows a non-vulnerable version, refreshi -The generated command targets a parent package that controls the vulnerable transitive `uuid@8.3.2`, not the unrelated direct `uuid@14.0.0` dependency. The exact parent and version depend on the dependency path CVE Lite CLI can verify. +The generated command targets a parent package that controls the vulnerable transitive `uuid@8.3.2`, not the unrelated direct `uuid@14.0.1` dependency. The exact parent and version depend on the dependency path CVE Lite CLI can verify. --- + ## Offline mode When running with `--offline` or `--offline-db`, CVE Lite CLI cannot make registry calls. This affects transitive remediation: From b2d73cdeb31d38e359995ae77adc02aa0b60cded Mon Sep 17 00:00:00 2001 From: Juliano Souza Date: Mon, 6 Jul 2026 10:43:59 -0300 Subject: [PATCH 3/3] docs: use verified transitive remediation example --- website/docs/how-remediation-works.mdx | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/website/docs/how-remediation-works.mdx b/website/docs/how-remediation-works.mdx index 4c11f92d..bc6e4805 100644 --- a/website/docs/how-remediation-works.mdx +++ b/website/docs/how-remediation-works.mdx @@ -479,34 +479,30 @@ The same package name can appear as both a direct dependency and a transitive de A version is direct only when that specific installed version matches the dependency declared by the project. Another installed version with the same package name can still be transitive when it arrives through unrelated parent packages. -For example, a project may declare `uuid@14.0.1` directly, while packages such as `@compodoc/live-server`, `nyc`, and `codecov` introduce a vulnerable `uuid@8.3.2` transitively: +For example, a project may declare `uuid@14.0.1` directly, while `nyc@15.1.0` introduces a vulnerable `uuid@8.3.2` transitively through `istanbul-lib-processinfo@2.0.3`: ```mermaid flowchart TD P(["Your project"]) P --> D["uuid@14.0.1\ndirect dependency"] - P --> L["@compodoc/live-server\nparent package"] - P --> N["nyc\nparent package"] - P --> C["codecov\nparent package"] - L --> V["uuid@8.3.2\ntransitive and vulnerable"] - N --> V - C --> V + P --> N["nyc@15.1.0\nparent package"] + N --> I["istanbul-lib-processinfo@2.0.3\nintermediate package"] + I --> V["uuid@8.3.2\ntransitive and vulnerable"] style P fill:#1e3a5f,color:#93c5fd,stroke:#3b82f6,padding:12px style D fill:#14532d,color:#86efac,stroke:#22c55e,padding:12px - style L fill:#1e293b,color:#cbd5e1,stroke:#475569,padding:12px style N fill:#1e293b,color:#cbd5e1,stroke:#475569,padding:12px - style C fill:#1e293b,color:#cbd5e1,stroke:#475569,padding:12px + style I fill:#1e293b,color:#cbd5e1,stroke:#475569,padding:12px style V fill:#7f1d1d,color:#fca5a5,stroke:#ef4444,padding:12px ``` -Running `npm install uuid@9.0.0` is the wrong fix in this scenario. It can install a third version of `uuid` and conflict with the already declared `uuid@14.0.1`, while the vulnerable transitive `uuid@8.3.2` may still remain in the lockfile. +Running `npm install uuid@9.0.0` targets the direct dependency slot in your `package.json`. It updates your declared direct dependency but leaves the vulnerable transitive `uuid@8.3.2` controlled by the parent package untouched in the lockfile. Because the vulnerable `uuid@8.3.2` is controlled by the parent package or dependency path that introduced it, remediation should target that parent instead of the unrelated direct `uuid@14.0.1` dependency. If the parent's declared range already allows a non-vulnerable version, refreshing the lockfile may resolve the finding. If it does not, the parent package may need to be upgraded to a version with a compatible, non-vulnerable dependency range. -When multiple parent packages introduce the same vulnerable transitive version, CVE Lite CLI selects the most actionable upgrade path based on the dependency paths it resolves in your lockfile. In this example, the generated command targets `nyc` as the selected parent upgrade path. +In this example, CVE Lite CLI selects `nyc` as the actionable parent upgrade path based on the dependency path it resolves in your lockfile. **Generated command:** @@ -533,11 +529,10 @@ When multiple parent packages introduce the same vulnerable transitive version, -The generated command targets a parent package that controls the vulnerable transitive `uuid@8.3.2`, not the unrelated direct `uuid@14.0.1` dependency. The exact parent and version depend on the dependency path CVE Lite CLI can verify. +The generated command targets the parent package that controls the vulnerable transitive `uuid@8.3.2`, not the unrelated direct `uuid@14.0.1` dependency. The exact parent and version depend on the dependency path CVE Lite CLI can verify. --- - ## Offline mode When running with `--offline` or `--offline-db`, CVE Lite CLI cannot make registry calls. This affects transitive remediation: