Skip to content

[main] SRVKP-12265: Add CVE remediation skill to console-plugin#1138

Open
openshift-cherrypick-robot wants to merge 1 commit into
openshift-pipelines:mainfrom
openshift-cherrypick-robot:cherry-pick-1136-to-main
Open

[main] SRVKP-12265: Add CVE remediation skill to console-plugin#1138
openshift-cherrypick-robot wants to merge 1 commit into
openshift-pipelines:mainfrom
openshift-cherrypick-robot:cherry-pick-1136-to-main

Conversation

@openshift-cherrypick-robot

Copy link
Copy Markdown
Contributor

This is an automated cherry-pick of #1136

/assign anwesha-palit-redhat

Signed-off-by: Ankur Sinha <anksinha@redhat.com>
@openshift-ci-robot

openshift-ci-robot commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

@openshift-cherrypick-robot: Ignoring requests to cherry-pick non-bug issues: SRVKP-12265

Details

In response to this:

This is an automated cherry-pick of #1136

/assign anwesha-palit-redhat

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci

openshift-ci Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: openshift-cherrypick-robot
Once this PR has been reviewed and has the lgtm label, please assign anwesha-palit-redhat for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (6) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Missing semver dependency 🐞 Bug ≡ Correctness
Description
scripts/fix-cves/analyze-deps.ts imports semver, but package.json doesn’t declare it, so the
script relies on transitive hoisting and can fail with a module-not-found error when semver isn’t
present at the top level.
Code

scripts/fix-cves/analyze-deps.ts[R3-7]

+import { execFileSync } from 'child_process';
+import * as fs from 'fs';
+import * as path from 'path';
+import semver from 'semver';
+
Evidence
The script has a direct import of semver, but the project manifest doesn’t list semver as a
direct dependency, so availability is incidental rather than guaranteed.

scripts/fix-cves/analyze-deps.ts[3-7]
package.json[1-192]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`scripts/fix-cves/analyze-deps.ts` imports `semver` but the repository doesn’t declare it in `package.json`. This makes the script non-hermetic: it can break when dependency/hoisting changes across branches.

## Issue Context
This script is intended to be used as a remediation tool across multiple release branches; it should have stable, explicit dependencies.

## Fix Focus Areas
- package.json[1-192]
- scripts/fix-cves/analyze-deps.ts[3-7]

## Suggested fix
- Add `semver` to `devDependencies` (or `dependencies`) with an appropriate pinned range.
- Run `yarn install` to update `yarn.lock` accordingly and commit both changes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. npm ls fallback misreports 🐞 Bug ≡ Correctness
Description
If npm ls --json output can’t be parsed (including when execFileSync hits the 10MB maxBuffer),
getAllInstalledVersions() returns an empty list and main falls back to only the hoisted
node_modules/<pkg> version, which can ignore nested vulnerable copies while still allowing an
already-remediated result.
Code

scripts/fix-cves/analyze-deps.ts[R54-63]

+function runCmd(cmd: string, args: string[]): string {
+  try {
+    return execFileSync(cmd, args, {
+      encoding: 'utf-8',
+      maxBuffer: 10 * 1024 * 1024,
+    });
+  } catch (e: any) {
+    return e.stdout ?? '';
+  }
+}
Evidence
Errors and parse failures are swallowed, and the control flow explicitly falls back to the single
hoisted version when no versions were collected, which can skip nested copies.

scripts/fix-cves/analyze-deps.ts[54-63]
scripts/fix-cves/analyze-deps.ts[141-149]
scripts/fix-cves/analyze-deps.ts[269-277]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The analysis relies on `npm ls --json` to enumerate *all* installed versions, but command failures/parsing failures are silently treated as “no versions found”, and the code falls back to the hoisted version only. This can produce incorrect remediation decisions.

## Issue Context
- `runCmd()` swallows command failures by returning `stdout` only.
- `getAllInstalledVersions()` swallows JSON parse errors.
- `main()` treats an empty list as a reason to trust `currentVersion`.

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[54-63]
- scripts/fix-cves/analyze-deps.ts[141-149]
- scripts/fix-cves/analyze-deps.ts[269-277]

## Suggested fix
- Make `runCmd` return `{ stdout, stderr, exitCode }` (or throw) so callers can distinguish success vs failure.
- In `getAllInstalledVersions`, if `npm ls` fails or JSON parsing fails, propagate an explicit error state.
- In `main`, if the full-tree enumeration failed, do **not** mark `already-remediated`; instead emit a strategy/reason indicating verification couldn’t be completed.
- Consider increasing `maxBuffer` substantially (or streaming output) to avoid truncation on large trees.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Substring parent matching 🐞 Bug ≡ Correctness
Description
getDirectParents() uses substring checks against raw yarn why output (line.includes(dep)), which
can misidentify direct parents (e.g., react matching react-dom) and produce incorrect
parentUpgradeSuggestions.
Code

scripts/fix-cves/analyze-deps.ts[R193-211]

+function getDirectParents(pkg: string): string[] {
+  const pjPath = path.join(process.cwd(), 'package.json');
+  if (!fs.existsSync(pjPath)) return [];
+  const pj = JSON.parse(fs.readFileSync(pjPath, 'utf-8'));
+  const allDirect = new Set([
+    ...Object.keys(pj.dependencies ?? {}),
+    ...Object.keys(pj.devDependencies ?? {}),
+  ]);
+
+  const output = runCmd('yarn', ['why', pkg]);
+  const parents = new Set<string>();
+  for (const line of output.split('\n')) {
+    for (const dep of allDirect) {
+      if (line.includes(dep)) parents.add(dep);
+    }
+  }
+  parents.delete(pkg);
+  return [...parents];
+}
Evidence
The code uses includes() across all direct dependency names, and the repo contains overlapping
direct dependency names (react and react-dom) that trigger false positives.

scripts/fix-cves/analyze-deps.ts[189-211]
package.json[108-114]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Direct parent detection is based on naive substring matches in unstructured `yarn why` output, which can return false positives and lead to incorrect recommended upgrades.

## Issue Context
This repo has direct deps with overlapping names (e.g. `react` and `react-dom`) making substring matching demonstrably ambiguous.

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[189-211]
- package.json[108-114]

## Suggested fix
- Switch to a structured source of truth:
 - Prefer `yarn why --json <pkg>` (Yarn emits JSON lines) and parse exact package identifiers, or
 - Use `npm ls <pkg> --all --json` to compute parent chains and then map to top-level deps precisely.
- If keeping text parsing, enforce exact package-name token matching (word boundaries / `@scope/name`-aware) rather than `includes()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Wrong FedRAMP base image 🐞 Bug ≡ Correctness
Description
SKILL.md instructs FedRAMP OS-CVE triage against ubi9/nodejs-24, but this repo’s build Dockerfile
uses ubi9/nodejs-20, so the workflow can report incorrect “fixed/not fixed” status for the actual
shipped image.
Code

.cursor/skills/fix-cves/SKILL.md[R81-90]

+#### C2. Check base images
+
+Query the Pyxis API to inspect the latest `ubi9/nodejs-24` and `ubi9/nginx-124` images.
+
+**Step 1 — Get the latest image ID for each repo:**
+
+```
+https://catalog.redhat.com/api/containers/v1/images?filter=repositories.repository%3D%3Dubi9/nodejs-24%3Barchitecture%3D%3Damd64&sort_by=creation_date%5Bdesc%5D&page_size=1
+```
+
Evidence
The skill’s instructions explicitly reference nodejs-24, while the Dockerfile shows nodejs-20 as the
builder image, creating a concrete mismatch.

.cursor/skills/fix-cves/SKILL.md[81-90]
Dockerfile[1-2]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
FedRAMP image triage guidance hardcodes the NodeJS base image repo/tag and does not match the repo’s actual container build arguments.

## Issue Context
The Dockerfile defines the builder image as `ubi9/nodejs-20`.

## Fix Focus Areas
- .cursor/skills/fix-cves/SKILL.md[81-90]
- Dockerfile[1-2]

## Suggested fix
- Update SKILL.md to query the correct base images used by this repo (currently `ubi9/nodejs-20` and `ubi9/nginx-124`).
- Optionally add a step instructing the user/bot to read the Dockerfile `ARG BUILDER`/`ARG RUNTIME` values first and then query Pyxis for those exact repos.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. Lockfile deletion guidance 🐞 Bug ⚙ Maintainability
Description
SKILL.md mandates deleting yarn.lock before remediation, which forces a full dependency
re-resolution and can introduce large unrelated dependency changes; the repo’s build scripts rely on
yarn install --immutable, which assumes the lockfile is the authoritative, stable dependency
graph.
Code

.cursor/skills/fix-cves/SKILL.md[R162-170]

+```bash
+git checkout <branch>
+git pull upstream <branch>
+rm -rf node_modules yarn.lock
+yarn install
+```
+
+**Critical**: Always remove both `node_modules` and `yarn.lock` and reinstall to regenerate the dependency graph from scratch and avoid stale resolutions.
+
Evidence
The skill explicitly deletes yarn.lock, while the repo’s build paths enforce immutable installs
which depend on the lockfile being stable and deliberate.

.cursor/skills/fix-cves/SKILL.md[162-170]
Dockerfile[16-18]
scripts/build_container.sh[23-25]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The skill instructs always removing `yarn.lock` as part of branch setup. This causes broad churn and undermines reproducibility, conflicting with the project’s immutable-install workflow.

## Issue Context
Both the Docker build and container build script run `yarn install --immutable`, indicating the repo expects the lockfile to be preserved and intentional.

## Fix Focus Areas
- .cursor/skills/fix-cves/SKILL.md[162-170]
- Dockerfile[16-18]
- scripts/build_container.sh[23-25]

## Suggested fix
- Change the setup instructions to remove only `node_modules` (and optionally `.yarn/cache` if needed), but keep `yarn.lock`.
- Recommend `yarn install --immutable` to ensure a clean, reproducible baseline before applying targeted upgrades/resolutions.
- Only regenerate `yarn.lock` when a remediation step actually requires a lockfile change (and keep diffs minimal).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

6. Nonportable shebang 🐞 Bug ☼ Reliability
Description
The analyze-deps.ts shebang passes multiple arguments via /usr/bin/env without -S, which is not
portable and can fail when executing the script directly (as opposed to invoking it via `npx ts-node
...`).
Code

scripts/fix-cves/analyze-deps.ts[1]

+#!/usr/bin/env npx ts-node --project scripts/fix-cves/tsconfig.json
Evidence
The script uses a multi-argument env shebang, which isn’t consistently supported across platforms
for direct execution.

scripts/fix-cves/analyze-deps.ts[1-2]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The shebang is not portable because most systems only support a single optional argument in a shebang unless using `env -S`.

## Issue Context
The skill documentation already invokes the script via `npx ts-node --project ...`, so the shebang is optional.

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[1-2]

## Suggested fix
- Either remove the shebang entirely, or change it to `#!/usr/bin/env -S npx ts-node --project scripts/fix-cves/tsconfig.json` for portability.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Qodo Logo

Comment on lines +3 to +7
import { execFileSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import semver from 'semver';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Missing semver dependency 🐞 Bug ≡ Correctness

scripts/fix-cves/analyze-deps.ts imports semver, but package.json doesn’t declare it, so the
script relies on transitive hoisting and can fail with a module-not-found error when semver isn’t
present at the top level.
Agent Prompt
## Issue description
`scripts/fix-cves/analyze-deps.ts` imports `semver` but the repository doesn’t declare it in `package.json`. This makes the script non-hermetic: it can break when dependency/hoisting changes across branches.

## Issue Context
This script is intended to be used as a remediation tool across multiple release branches; it should have stable, explicit dependencies.

## Fix Focus Areas
- package.json[1-192]
- scripts/fix-cves/analyze-deps.ts[3-7]

## Suggested fix
- Add `semver` to `devDependencies` (or `dependencies`) with an appropriate pinned range.
- Run `yarn install` to update `yarn.lock` accordingly and commit both changes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +54 to +63
function runCmd(cmd: string, args: string[]): string {
try {
return execFileSync(cmd, args, {
encoding: 'utf-8',
maxBuffer: 10 * 1024 * 1024,
});
} catch (e: any) {
return e.stdout ?? '';
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Npm ls fallback misreports 🐞 Bug ≡ Correctness

If npm ls --json output can’t be parsed (including when execFileSync hits the 10MB maxBuffer),
getAllInstalledVersions() returns an empty list and main falls back to only the hoisted
node_modules/<pkg> version, which can ignore nested vulnerable copies while still allowing an
already-remediated result.
Agent Prompt
## Issue description
The analysis relies on `npm ls --json` to enumerate *all* installed versions, but command failures/parsing failures are silently treated as “no versions found”, and the code falls back to the hoisted version only. This can produce incorrect remediation decisions.

## Issue Context
- `runCmd()` swallows command failures by returning `stdout` only.
- `getAllInstalledVersions()` swallows JSON parse errors.
- `main()` treats an empty list as a reason to trust `currentVersion`.

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[54-63]
- scripts/fix-cves/analyze-deps.ts[141-149]
- scripts/fix-cves/analyze-deps.ts[269-277]

## Suggested fix
- Make `runCmd` return `{ stdout, stderr, exitCode }` (or throw) so callers can distinguish success vs failure.
- In `getAllInstalledVersions`, if `npm ls` fails or JSON parsing fails, propagate an explicit error state.
- In `main`, if the full-tree enumeration failed, do **not** mark `already-remediated`; instead emit a strategy/reason indicating verification couldn’t be completed.
- Consider increasing `maxBuffer` substantially (or streaming output) to avoid truncation on large trees.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +193 to +211
function getDirectParents(pkg: string): string[] {
const pjPath = path.join(process.cwd(), 'package.json');
if (!fs.existsSync(pjPath)) return [];
const pj = JSON.parse(fs.readFileSync(pjPath, 'utf-8'));
const allDirect = new Set([
...Object.keys(pj.dependencies ?? {}),
...Object.keys(pj.devDependencies ?? {}),
]);

const output = runCmd('yarn', ['why', pkg]);
const parents = new Set<string>();
for (const line of output.split('\n')) {
for (const dep of allDirect) {
if (line.includes(dep)) parents.add(dep);
}
}
parents.delete(pkg);
return [...parents];
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Substring parent matching 🐞 Bug ≡ Correctness

getDirectParents() uses substring checks against raw yarn why output (line.includes(dep)), which
can misidentify direct parents (e.g., react matching react-dom) and produce incorrect
parentUpgradeSuggestions.
Agent Prompt
## Issue description
Direct parent detection is based on naive substring matches in unstructured `yarn why` output, which can return false positives and lead to incorrect recommended upgrades.

## Issue Context
This repo has direct deps with overlapping names (e.g. `react` and `react-dom`) making substring matching demonstrably ambiguous.

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[189-211]
- package.json[108-114]

## Suggested fix
- Switch to a structured source of truth:
  - Prefer `yarn why --json <pkg>` (Yarn emits JSON lines) and parse exact package identifiers, or
  - Use `npm ls <pkg> --all --json` to compute parent chains and then map to top-level deps precisely.
- If keeping text parsing, enforce exact package-name token matching (word boundaries / `@scope/name`-aware) rather than `includes()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +81 to +90
#### C2. Check base images

Query the Pyxis API to inspect the latest `ubi9/nodejs-24` and `ubi9/nginx-124` images.

**Step 1 — Get the latest image ID for each repo:**

```
https://catalog.redhat.com/api/containers/v1/images?filter=repositories.repository%3D%3Dubi9/nodejs-24%3Barchitecture%3D%3Damd64&sort_by=creation_date%5Bdesc%5D&page_size=1
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Wrong fedramp base image 🐞 Bug ≡ Correctness

SKILL.md instructs FedRAMP OS-CVE triage against ubi9/nodejs-24, but this repo’s build Dockerfile
uses ubi9/nodejs-20, so the workflow can report incorrect “fixed/not fixed” status for the actual
shipped image.
Agent Prompt
## Issue description
FedRAMP image triage guidance hardcodes the NodeJS base image repo/tag and does not match the repo’s actual container build arguments.

## Issue Context
The Dockerfile defines the builder image as `ubi9/nodejs-20`.

## Fix Focus Areas
- .cursor/skills/fix-cves/SKILL.md[81-90]
- Dockerfile[1-2]

## Suggested fix
- Update SKILL.md to query the correct base images used by this repo (currently `ubi9/nodejs-20` and `ubi9/nginx-124`).
- Optionally add a step instructing the user/bot to read the Dockerfile `ARG BUILDER`/`ARG RUNTIME` values first and then query Pyxis for those exact repos.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-code-review qodo-code-review Bot added documentation Improvements or additions to documentation enhancement New feature or request labels Jun 23, 2026
@arvindk-softwaredev

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Looks Good to Me Label label Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request lgtm Looks Good to Me Label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants