Skip to content

SRVKP-12265: Add CVE remediation skill to console-plugin#1136

Open
ankrsinha wants to merge 1 commit into
openshift-pipelines:masterfrom
ankrsinha:feat/SRVKP-12265
Open

SRVKP-12265: Add CVE remediation skill to console-plugin#1136
ankrsinha wants to merge 1 commit into
openshift-pipelines:masterfrom
ankrsinha:feat/SRVKP-12265

Conversation

@ankrsinha

@ankrsinha ankrsinha commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a Cursor AI skill and a TypeScript analysis script to automate CVE remediation across console-plugin release branches, with Jira integration and FedRAMP image triage.

Files Added

File Purpose
.cursor/skills/fix-cves/SKILL.md AI skill definition — 4-phase workflow with 3 input modes
scripts/fix-cves/analyze-deps.ts Dependency analysis script — determines remediation strategy
scripts/fix-cves/tsconfig.json TypeScript config for ts-node execution

Setup

1. Install tools

Tool Install / Verify
Node.js + Yarn Already required for console-plugin
gh CLI Install, then run gh auth login
Git remotes Verify with git remote -v — you need upstream (main repo) and origin (your fork)

2. Install Cursor plugins

Plugin Required for
Atlassian Mode B — fetching Jira issues, posting comments, PR linking, status transitions

To install:

  1. Go to Settings → Plugins → Browse Marketplace
  2. Search for Atlassian and click Add to Cursor
  3. Complete the authorization when prompted — this connects Cursor to your Jira account
Screenshot From 2026-06-22 15-42-05

Mode A works without the Atlassian plugin. Mode C uses public Red Hat APIs and needs no plugins.

3. Configure Cursor Agent settings

Go to Cursor Settings → Agents and configure the following:

Auto-Run Mode
Set to Allowlist (with Sandbox) or higher.

Command Allowlist
Add these commands so the skill can run them without prompting:

git, yarn, npx, npm, gh, rm

MCP Allowlist
Add the following so the skill can interact with Jira automatically:

atlassian:*

Fetch Domain Allowlist
Add these domains:

github.com, access.redhat.com, catalog.redhat.com
  • github.com — PR creation and git push (Modes A & B)
  • access.redhat.com, catalog.redhat.com — Red Hat APIs (Mode C)

Auto-Run Network Access
sandbox.json + Defaults works for most cases. If Red Hat API calls are blocked, switch to Allow All.

Usage

Open Cursor Agent chat and use one of the following prompts:

Mode A — Paste Jira descriptions (no Atlassian plugin needed)

Use the CVE skill with Mode A

Fix these CVEs on release-v1.20.x:

<paste SRVKP ticket description here>

Mode B — Fetch from Jira (requires Atlassian plugin)

Use the CVE skill with Mode B

SRVKP-12345, SRVKP-12346 on release-v1.20.x

Also check for release-v1.15.x, give Jira if any

Fix the CVEs based on the skill mentioned

Mode C — FedRAMP image CVE triage (no plugins needed)

Use the CVE skill with Mode C

Check if these FedRAMP CVEs are fixed in the base images:
CVE-2026-43618, CVE-2026-29518, CVE-2026-45186, CVE-2026-22020

Remediation Strategies

The analysis script inspects the dependency tree and returns one of:

Strategy When
already-remediated Installed version already meets the fix
direct-upgrade Package is a direct dependency — yarn up
parent-upgrade Upgrading a direct parent resolves the transitive fix
resolution Force version via resolutions (last resort)
triage-needed Fix unavailable on npm or blocked by SDK constraints

Jira Automation (Mode B)

  • Posts comments with native reporter @mention notifications
  • Includes yarn why / npm ls evidence as bash code blocks
  • Links PR to the Jira Pull Request field
  • Transitions issue to Code Review status

Workflow

  1. Input — parse CVEs from Jira tickets or pasted descriptions
  2. Branch Setup & Fix Loop — checkout, clean install, analyze, apply fixes, verify with yarn build / yarn test
  3. Create PR — structured description with CVE table, validation results, and collapsible verification evidence
  4. Repeat — process additional release branches independently

Demo

Screen recording

CVE-fix-demo.mp4

Screenshot of Jira comment added

image

@qodo-code-review

qodo-code-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (5) 📘 Rule violations (0) 📎 Requirement gaps (2) 📜 Skill insights (0)

Context used

Grey Divider


Action required

1. --fixed-version rejects ranges 📎 Requirement gap ≡ Correctness
Description
scripts/fix-cves/analyze-deps.ts requires --fixed-version to pass semver.valid(), which
rejects common Jira/advisory formats like >=4.0.8. This can prevent the skill from correctly
determining fixed versions and running analysis as intended.
Code

scripts/fix-cves/analyze-deps.ts[R84-87]

+  if (!semver.valid(fixedVersion)) {
+    console.error(`Invalid semver version: ${fixedVersion}`);
+    process.exit(1);
+  }
Evidence
The skill instructs extracting fixed versions from Jira text near operators like >=, but the
analysis script exits unless --fixed-version is an exact semver; this mismatch can block
fixed-version determination/analysis required by the workflow.

Skill determines required fixed versions and detects dependencies already fixed
.cursor/skills/fix-cves/SKILL.md[27-35]
scripts/fix-cves/analyze-deps.ts[84-87]

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

## Issue description
`analyze-deps.ts` rejects `--fixed-version` values unless they are an exact semver, but the skill instructions indicate Jira text may include operators like `>=`.

## Issue Context
The CVE workflow depends on passing fixed-version values extracted from Jira/advisories into `scripts/fix-cves/analyze-deps.ts`.

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[65-89]
- .cursor/skills/fix-cves/SKILL.md[27-37]

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


2. No workflow validation evidence 📎 Requirement gap ☼ Reliability
Description
The added skill documentation includes only placeholder SRVKP/CVE examples and does not record any
validation against real CVE Jira examples and release branches. This leaves the end-to-end workflow
correctness unverified per the compliance requirement.
Code

.cursor/skills/fix-cves/SKILL.md[R146-150]

+```
+| SRVKP      | CVE ID          | Package     | Fixed Version | Status             |
+|------------|-----------------|-------------|--------------:|--------------------|
+| [SRVKP-1234](https://redhat.atlassian.net/browse/SRVKP-1234) | CVE-2024-12345 | micromatch  | 4.0.8         | pending            |
+```
Evidence
Rule 7 requires validation using existing CVE Jira examples and release branches with correctness
review; the added documentation shows only illustrative placeholders (e.g., [SRVKP-1234](https://redhat.atlassian.net/browse/SRVKP-1234),
CVE-2024-12345) and a procedural checklist, but no recorded real validation runs/examples.

Workflow validated against existing CVE Jira examples and release branches with correctness review
.cursor/skills/fix-cves/SKILL.md[146-150]
.cursor/skills/fix-cves/SKILL.md[510-530]

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 documentation does not include any evidence that the workflow was validated against existing/real CVE Jira examples and corresponding release branches.

## Issue Context
Compliance requires demonstrating end-to-end validation and correctness review using known Jira examples and relevant release branches.

## Fix Focus Areas
- .cursor/skills/fix-cves/SKILL.md[10-14]
- .cursor/skills/fix-cves/SKILL.md[139-152]
- .cursor/skills/fix-cves/SKILL.md[510-530]

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


3. npm ls truncation misclassifies 🐞 Bug ≡ Correctness
Description
runCmd() caps output at 10MB and getAllInstalledVersions() silently returns [] on JSON parse
failure, which can cause nested vulnerable copies to be missed and the CVE to be reported as
already-remediated based only on the hoisted version. This can produce false assurance and skipped
remediation on branches with large dependency trees.
Code

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

+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 ?? '';
+  }
+}
+
+function parseArgs(): CLIArgs {
+  const args = process.argv.slice(2);
+  let pkg = '';
+  let fixedVersion = '';
+  for (let i = 0; i < args.length; i++) {
+    if (args[i] === '--package' && args[i + 1]) pkg = args[++i];
+    else if (args[i] === '--fixed-version' && args[i + 1])
+      fixedVersion = args[++i];
+  }
+  if (!pkg || !fixedVersion) {
+    console.error(
+      'Usage: analyze-deps.ts --package <name> --fixed-version <ver>',
+    );
+    process.exit(1);
+  }
+  if (!/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(pkg)) {
+    console.error(`Invalid package name: ${pkg}`);
+    process.exit(1);
+  }
+  if (!semver.valid(fixedVersion)) {
+    console.error(`Invalid semver version: ${fixedVersion}`);
+    process.exit(1);
+  }
+  return { package: pkg, fixedVersion };
+}
+
+/**
+ * Run `yarn why <pkg>` and return raw output + parsed dependency chains.
+ */
+function getYarnWhy(pkg: string): { raw: string; chains: string[] } {
+  const raw = runCmd('yarn', ['why', pkg]);
+  const chains: string[] = [];
+  for (const line of raw.split('\n')) {
+    const trimmed = line.trim();
+    if (trimmed && !trimmed.startsWith('=') && !trimmed.startsWith('Done')) {
+      chains.push(trimmed);
+    }
+  }
+  return { raw, chains };
+}
+
+/**
+ * Determine if a package is a transitive dependency of any SDK package
+ * by inspecting `yarn why` output for SDK package names in the chains.
+ */
+function isTransitiveSDKDep(chains: string[]): boolean {
+  return chains.some((chain) =>
+    SDK_PACKAGES.some((sdk) => chain.includes(sdk)),
+  );
+}
+
+/**
+ * Get the currently installed version from node_modules or yarn.lock.
+ */
+function getCurrentVersion(pkg: string): string | null {
+  const nmPath = path.join(
+    process.cwd(),
+    'node_modules',
+    ...pkg.split('/'),
+    'package.json',
+  );
+  if (fs.existsSync(nmPath)) {
+    try {
+      const pj = JSON.parse(fs.readFileSync(nmPath, 'utf-8'));
+      return pj.version ?? null;
+    } catch {
+      return null;
+    }
+  }
+  return null;
+}
+
+/**
+ * Get ALL installed versions of a package across the entire node_modules tree.
+ * Catches nested/duplicate copies that the hoisted-only check would miss.
+ */
+function getAllInstalledVersions(pkg: string): string[] {
+  const output = runCmd('npm', ['ls', '--all', pkg, '--json']);
+  const versions = new Set<string>();
+  try {
+    const tree = JSON.parse(output);
+    findVersions(tree, pkg, versions);
+  } catch {}
+  return [...versions];
+}
Evidence
The buffer limit and swallowed JSON parse errors can cause installedVersions to be empty even when
nested copies exist; the subsequent fallback path can then misclassify the state of remediation.

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
`npm ls --json` output can exceed the 10MB buffer and/or be emitted alongside non-fatal errors; today the script suppresses parse errors and treats the result as "no versions found", potentially falling back to a single hoisted version and incorrectly concluding the CVE is already remediated.

## Issue Context
This script is intended to drive automated CVE remediation decisions; missing a nested vulnerable copy is a correctness failure.

## 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 approach
- Increase `maxBuffer` significantly (or make it configurable).
- Change `getAllInstalledVersions` to surface parse/truncation failure explicitly (e.g., return `{ versions: string[], error?: string }`).
- In `main()`, if the full-tree scan fails, **do not** fall back to `currentVersion` and mark `already-remediated`; instead emit `strategy: 'triage-needed'` (or a new strategy like `analysis-failed`) with a clear `reason` and include raw stderr/stdout snippets for debugging.

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


View more (1)
4. Deletes yarn.lock in workflow 🐞 Bug ☼ Reliability
Description
The skill instructs deleting yarn.lock on every branch sync, which forces a full dependency
re-resolution and can upgrade many unrelated packages, creating large/noisy PRs and potentially
breaking release branches. This undermines the goal of targeted CVE remediation and makes results
harder to review and reproduce.
Code

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

+```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 mandates deleting the lockfile, while the repo is configured to use Yarn 4 with
a generated lockfile, making lockfile deletion likely to cause broad re-resolution.

.cursor/skills/fix-cves/SKILL.md[162-170]
package.json[7-7]
yarn.lock[1-6]

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’s “clean install” step removes `yarn.lock`, which broadens changes beyond the intended CVE fixes.

## Issue Context
This repo uses Yarn 4 and checks in `yarn.lock` for reproducible installs.

## Fix Focus Areas
- .cursor/skills/fix-cves/SKILL.md[162-170]

## Suggested fix approach
- Update the workflow to:
 - Remove only `node_modules` (optional) but **keep** `yarn.lock`.
 - Prefer `yarn install --immutable` right after checkout/pull to ensure the lockfile matches the branch.
 - Only regenerate `yarn.lock` as a result of intentional remediation commands (`yarn up ...`, adding `resolutions`, etc.).
- If you still want a “full refresh” mode, document it as an explicit opt-in step, not the default.

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



Remediation recommended

5. No not-installed classification 🐞 Bug ≡ Correctness
Description
If the target package is not installed (currentVersion=null and installedVersions=[]), the
script still selects a remediation strategy (e.g., resolution/direct-upgrade) rather than
reporting the package as absent on the branch. This can drive unnecessary dependency changes and
misleading Jira comments for CVEs that don’t apply to a given release branch’s dependency tree.
Code

scripts/fix-cves/analyze-deps.ts[R264-333]

+function main(): void {
+  const args = parseArgs();
+  const { raw: yarnWhyRaw, chains } = getYarnWhy(args.package);
+  const currentVersion = getCurrentVersion(args.package);
+
+  // Full-tree check: verify ALL installed copies satisfy the fix, not just the
+  // hoisted one. Falls back to the hoisted version if npm ls returns nothing.
+  let installedVersions = getAllInstalledVersions(args.package);
+  if (installedVersions.length === 0 && currentVersion) {
+    installedVersions = [currentVersion];
+  }
+  const allSatisfied =
+    installedVersions.length > 0 &&
+    installedVersions.every((v) => isVersionSatisfied(v, args.fixedVersion));
+  if (allSatisfied) {
+    const sharedWithSDK = isTransitiveSDKDep(chains);
+    const result: AnalysisResult = {
+      package: args.package,
+      currentVersion,
+      fixedVersion: args.fixedVersion,
+      isSharedWithSDK: sharedWithSDK,
+      dependencyChains: chains,
+      directParents: [],
+      parentUpgradeAvailable: false,
+      parentUpgradeSuggestions: [],
+      fixedVersionAvailable: true,
+      availableVersions: [],
+      strategy: 'already-remediated',
+      reason: `All ${installedVersions.length} installed copy/copies satisfy >= ${args.fixedVersion}`,
+      yarnWhyRaw,
+    };
+    console.log(JSON.stringify(result, null, 2));
+    return;
+  }
+
+  const sharedWithSDK = isTransitiveSDKDep(chains);
+  const versions = getAvailableVersions(args.package);
+  const fixedAvailable = versions.includes(args.fixedVersion);
+  const direct = isDirectDep(args.package);
+  const directParents = direct ? [] : getDirectParents(args.package);
+  const parentSuggestions = direct
+    ? []
+    : checkParentUpgrades(args.package, args.fixedVersion, directParents);
+
+  let strategy: AnalysisResult['strategy'];
+  let reason: string;
+
+  if (!fixedAvailable) {
+    strategy = 'triage-needed';
+    reason = `Fixed version ${args.fixedVersion} not published on npm`;
+  } else if (direct) {
+    strategy = 'direct-upgrade';
+    reason = sharedWithSDK
+      ? 'Direct dependency also pulled by SDK; upgrade directly, SDK will use the hoisted version'
+      : 'Direct dependency — safe to upgrade';
+  } else if (parentSuggestions.length > 0) {
+    strategy = 'parent-upgrade';
+    reason = `Upgrading a direct parent pulls in the fix: ${parentSuggestions.join(
+      '; ',
+    )}`;
+  } else if (sharedWithSDK) {
+    strategy = 'resolution';
+    reason =
+      'Transitive dep of SDK; no parent upgrade resolves it — use resolutions to force the fixed version';
+  } else {
+    strategy = 'resolution';
+    reason =
+      'Transitive dependency; no parent upgrade resolves it — use resolutions as last resort';
+  }
+
Evidence
The current logic only considers already-remediated when at least one installed version is found;
absence falls through into remediation strategy selection.

scripts/fix-cves/analyze-deps.ts[119-135]
scripts/fix-cves/analyze-deps.ts[141-149]
scripts/fix-cves/analyze-deps.ts[269-307]

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

## Issue description
When a package isn't present in the installed dependency graph, the script should not recommend remediation steps.

## Issue Context
Currently `installedVersions.length === 0` leads into strategy selection rather than a definitive "not installed" outcome.

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[119-135]
- scripts/fix-cves/analyze-deps.ts[141-149]
- scripts/fix-cves/analyze-deps.ts[264-333]

## Suggested fix approach
- Add an explicit check after computing `installedVersions`:
 - If `installedVersions.length === 0` and `currentVersion === null`, emit `strategy: 'already-remediated'` (or introduce a clearer `not-installed`/`not-applicable` strategy) with `reason: 'Package not installed on this branch'`.
- Optionally: use `yarn why` result to confirm absence and include that in `reason`/output.

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


6. Broken multi-arg shebang 🐞 Bug ☼ Reliability
Description
The script’s shebang uses /usr/bin/env with multiple arguments, which is not portable and
typically fails because env receives the remainder as a single argument. Running
scripts/fix-cves/analyze-deps.ts directly as an executable will likely not work.
Code

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

+#!/usr/bin/env npx ts-node --project scripts/fix-cves/tsconfig.json
Evidence
The added file begins with a multi-argument /usr/bin/env shebang which is commonly unsupported
without env -S.

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

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 current shebang is not a valid multi-arg env invocation on many systems.

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

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

## Suggested fix approach
- Either remove the shebang entirely, or change it to a portable form such as:
 - `#!/usr/bin/env -S npx ts-node --project scripts/fix-cves/tsconfig.json`
- Keep the documented `npx ts-node --project ...` invocation as the primary supported path.

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


7. Parent detection uses substrings 🐞 Bug ≡ Correctness
Description
getDirectParents() identifies parents by checking line.includes(dep) against yarn why output,
which can produce false matches when package names overlap (e.g., react vs react-dom) or appear
in unrelated text. This can generate incorrect parent-upgrade suggestions and skew remediation
strategy selection.
Code

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

+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 current implementation treats any substring match as a parent, which is not a safe inference
from free-form CLI output.

scripts/fix-cves/analyze-deps.ts[193-210]

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

## Issue description
Substring matching on `yarn why` output is not a reliable way to infer direct parents.

## Issue Context
Wrong parents can lead to proposing upgrades that don’t actually remediate the CVE (or cause unnecessary churn).

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[193-210]

## Suggested fix approach
- Prefer structured output (`yarn why --json`) and parse the JSON to extract dependents.
- If staying with text parsing, add proper token/boundary matching (escape package names and match `dep@` / quoted segments) to avoid substring collisions.

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


Grey Divider

Qodo Logo

Comment thread scripts/fix-cves/analyze-deps.ts Outdated
Comment thread scripts/fix-cves/analyze-deps.ts
@qodo-code-review qodo-code-review Bot added documentation Improvements or additions to documentation enhancement New feature or request labels Jun 22, 2026
@ankrsinha ankrsinha changed the title feat: Add CVE fix skill with dependency analysis script SRVKP-12265: Add CVE remediation skill to console-plugin Jun 22, 2026
@openshift-ci-robot

openshift-ci-robot commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

@ankrsinha: This pull request references SRVKP-12265 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

Adds a Cursor AI skill and a TypeScript analysis script to automate CVE remediation across console-plugin release branches, with Jira integration and FedRAMP image triage.

Files Added

File Purpose
.cursor/skills/fix-cves/SKILL.md AI skill definition — 4-phase workflow with 3 input modes
scripts/fix-cves/analyze-deps.ts Dependency analysis script — determines remediation strategy
scripts/fix-cves/tsconfig.json TypeScript config for ts-node execution

Setup

1. Install tools

Tool Install / Verify
Node.js + Yarn Already required for console-plugin
gh CLI Install, then run gh auth login
Git remotes Verify with git remote -v — you need upstream (main repo) and origin (your fork)

2. Install Cursor plugins

Go to Cursor Settings → Plugins and install:

Plugin Required for
Atlassian Mode B — fetching Jira issues, posting comments, PR linking, status transitions

Mode A works without the Atlassian plugin. Mode C uses public Red Hat APIs and needs no plugins.

After installing, authenticate the Atlassian plugin when prompted.

3. Configure Cursor Agent settings

Go to Cursor Settings → Agents and configure the following:

Auto-Run Mode
Set to Allowlist (with Sandbox) or higher.

Command Allowlist
Add these commands so the skill can run them without prompting:

git, yarn, npx, npm, gh, rm

MCP Allowlist
Add the following so the skill can interact with Jira automatically:

atlassian:*

Fetch Domain Allowlist
Add these domains:

github.com, access.redhat.com, catalog.redhat.com
  • github.com — PR creation and git push (Modes A & B)
  • access.redhat.com, catalog.redhat.com — Red Hat APIs (Mode C)

Auto-Run Network Access
sandbox.json + Defaults works for most cases. If Red Hat API calls are blocked, switch to Allow All.

Usage

Open Cursor Agent chat and use one of the following prompts:

Mode A — Paste Jira descriptions (no Atlassian plugin needed)

Use the CVE skill with Mode A

Fix these CVEs on release-v1.20.x:

<paste SRVKP ticket description here>

Mode B — Fetch from Jira (requires Atlassian plugin)

Use the CVE skill with Mode B

SRVKP-12345, [SRVKP-12346](https://redhat.atlassian.net/browse/SRVKP-12346) on release-v1.20.x

Also check for release-v1.15.x, give Jira if any

Fix the CVEs based on the skill mentioned

Mode C — FedRAMP image CVE triage (no plugins needed)

Use the CVE skill with Mode C

Check if these FedRAMP CVEs are fixed in the base images:
CVE-2026-43618, CVE-2026-29518, CVE-2026-45186, CVE-2026-22020

Remediation Strategies

The analysis script inspects the dependency tree and returns one of:

Strategy When
already-remediated Installed version already meets the fix
direct-upgrade Package is a direct dependency — yarn up
parent-upgrade Upgrading a direct parent resolves the transitive fix
resolution Force version via resolutions (last resort)
triage-needed Fix unavailable on npm or blocked by SDK constraints

Jira Automation (Mode B)

  • Posts comments with native reporter @mention notifications
  • Includes yarn why / npm ls evidence as bash code blocks
  • Links PR to the Jira Pull Request field
  • Transitions issue to Code Review status

Workflow

  1. Input — parse CVEs from Jira tickets or pasted descriptions
  2. Branch Setup & Fix Loop — checkout, clean install, analyze, apply fixes, verify with yarn build / yarn test
  3. Create PR — structured description with CVE table, validation results, and collapsible verification evidence
  4. Repeat — process additional release branches independently

Demo

Screen recording

CVE-fix-demo.mp4

Screenshot of Jira comment added

image

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.

@anwesha-palit-redhat anwesha-palit-redhat requested review from arvindk-softwaredev and removed request for pratap0007 June 22, 2026 10:08
Signed-off-by: Ankur Sinha <anksinha@redhat.com>
anwesha-palit-redhat

This comment was marked as duplicate.

@openshift-ci openshift-ci Bot added the lgtm Looks Good to Me Label label Jun 22, 2026
@openshift-ci

openshift-ci Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ankrsinha, anwesha-palit-redhat

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

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [anwesha-palit-redhat]

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

@openshift-ci openshift-ci Bot added the approved Label for Approved PRs label Jun 22, 2026
@openshift-ci openshift-ci Bot removed the lgtm Looks Good to Me Label label Jun 22, 2026
@openshift-ci

openshift-ci Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

New changes are detected. LGTM label has been removed.

@anwesha-palit-redhat

Copy link
Copy Markdown
Contributor

/agentic_review

Comment on lines +84 to +87
if (!semver.valid(fixedVersion)) {
console.error(`Invalid semver version: ${fixedVersion}`);
process.exit(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

1. --fixed-version rejects ranges 📎 Requirement gap ≡ Correctness

scripts/fix-cves/analyze-deps.ts requires --fixed-version to pass semver.valid(), which
rejects common Jira/advisory formats like >=4.0.8. This can prevent the skill from correctly
determining fixed versions and running analysis as intended.
Agent Prompt
## Issue description
`analyze-deps.ts` rejects `--fixed-version` values unless they are an exact semver, but the skill instructions indicate Jira text may include operators like `>=`.

## Issue Context
The CVE workflow depends on passing fixed-version values extracted from Jira/advisories into `scripts/fix-cves/analyze-deps.ts`.

## Fix Focus Areas
- scripts/fix-cves/analyze-deps.ts[65-89]
- .cursor/skills/fix-cves/SKILL.md[27-37]

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

By design, the script always receives a concrete version (e.g. 4.0.8), not a range. The AI agent extracts the version number from Jira text like "fixed in >= 4.0.8" before passing it to the script. The semver.gte() comparison requires a concrete version to work.

Comment on lines +146 to +150
```
| SRVKP | CVE ID | Package | Fixed Version | Status |
|------------|-----------------|-------------|--------------:|--------------------|
| SRVKP-1234 | CVE-2024-12345 | micromatch | 4.0.8 | pending |
```

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. No workflow validation evidence 📎 Requirement gap ☼ Reliability

The added skill documentation includes only placeholder SRVKP/CVE examples and does not record any
validation against real CVE Jira examples and release branches. This leaves the end-to-end workflow
correctness unverified per the compliance requirement.
Agent Prompt
## Issue description
The skill documentation does not include any evidence that the workflow was validated against existing/real CVE Jira examples and corresponding release branches.

## Issue Context
Compliance requires demonstrating end-to-end validation and correctness review using known Jira examples and relevant release branches.

## Fix Focus Areas
- .cursor/skills/fix-cves/SKILL.md[10-14]
- .cursor/skills/fix-cves/SKILL.md[139-152]
- .cursor/skills/fix-cves/SKILL.md[510-530]

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The PR already includes a screen recording demo and a Jira comment screenshot as validation.

Comment on lines +54 to +149
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 ?? '';
}
}

function parseArgs(): CLIArgs {
const args = process.argv.slice(2);
let pkg = '';
let fixedVersion = '';
for (let i = 0; i < args.length; i++) {
if (args[i] === '--package' && args[i + 1]) pkg = args[++i];
else if (args[i] === '--fixed-version' && args[i + 1])
fixedVersion = args[++i];
}
if (!pkg || !fixedVersion) {
console.error(
'Usage: analyze-deps.ts --package <name> --fixed-version <ver>',
);
process.exit(1);
}
if (!/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(pkg)) {
console.error(`Invalid package name: ${pkg}`);
process.exit(1);
}
if (!semver.valid(fixedVersion)) {
console.error(`Invalid semver version: ${fixedVersion}`);
process.exit(1);
}
return { package: pkg, fixedVersion };
}

/**
* Run `yarn why <pkg>` and return raw output + parsed dependency chains.
*/
function getYarnWhy(pkg: string): { raw: string; chains: string[] } {
const raw = runCmd('yarn', ['why', pkg]);
const chains: string[] = [];
for (const line of raw.split('\n')) {
const trimmed = line.trim();
if (trimmed && !trimmed.startsWith('=') && !trimmed.startsWith('Done')) {
chains.push(trimmed);
}
}
return { raw, chains };
}

/**
* Determine if a package is a transitive dependency of any SDK package
* by inspecting `yarn why` output for SDK package names in the chains.
*/
function isTransitiveSDKDep(chains: string[]): boolean {
return chains.some((chain) =>
SDK_PACKAGES.some((sdk) => chain.includes(sdk)),
);
}

/**
* Get the currently installed version from node_modules or yarn.lock.
*/
function getCurrentVersion(pkg: string): string | null {
const nmPath = path.join(
process.cwd(),
'node_modules',
...pkg.split('/'),
'package.json',
);
if (fs.existsSync(nmPath)) {
try {
const pj = JSON.parse(fs.readFileSync(nmPath, 'utf-8'));
return pj.version ?? null;
} catch {
return null;
}
}
return null;
}

/**
* Get ALL installed versions of a package across the entire node_modules tree.
* Catches nested/duplicate copies that the hoisted-only check would miss.
*/
function getAllInstalledVersions(pkg: string): string[] {
const output = runCmd('npm', ['ls', '--all', pkg, '--json']);
const versions = new Set<string>();
try {
const tree = JSON.parse(output);
findVersions(tree, pkg, versions);
} catch {}
return [...versions];
}

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. Npm ls truncation misclassifies 🐞 Bug ≡ Correctness

runCmd() caps output at 10MB and getAllInstalledVersions() silently returns [] on JSON parse
failure, which can cause nested vulnerable copies to be missed and the CVE to be reported as
already-remediated based only on the hoisted version. This can produce false assurance and skipped
remediation on branches with large dependency trees.
Agent Prompt
## Issue description
`npm ls --json` output can exceed the 10MB buffer and/or be emitted alongside non-fatal errors; today the script suppresses parse errors and treats the result as "no versions found", potentially falling back to a single hoisted version and incorrectly concluding the CVE is already remediated.

## Issue Context
This script is intended to drive automated CVE remediation decisions; missing a nested vulnerable copy is a correctness failure.

## 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 approach
- Increase `maxBuffer` significantly (or make it configurable).
- Change `getAllInstalledVersions` to surface parse/truncation failure explicitly (e.g., return `{ versions: string[], error?: string }`).
- In `main()`, if the full-tree scan fails, **do not** fall back to `currentVersion` and mark `already-remediated`; instead emit `strategy: 'triage-needed'` (or a new strategy like `analysis-failed`) with a clear `reason` and include raw stderr/stdout snippets for debugging.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The full npm ls --all --json output for this project is ~760KB, well under the 10MB buffer. The skill also runs a separate verification step (Phase 2d) that would catch any missed copies.

Comment on lines +162 to +169
```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.

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

5. Deletes yarn.lock in workflow 🐞 Bug ☼ Reliability

The skill instructs deleting yarn.lock on every branch sync, which forces a full dependency
re-resolution and can upgrade many unrelated packages, creating large/noisy PRs and potentially
breaking release branches. This undermines the goal of targeted CVE remediation and makes results
harder to review and reproduce.
Agent Prompt
## Issue description
The skill’s “clean install” step removes `yarn.lock`, which broadens changes beyond the intended CVE fixes.

## Issue Context
This repo uses Yarn 4 and checks in `yarn.lock` for reproducible installs.

## Fix Focus Areas
- .cursor/skills/fix-cves/SKILL.md[162-170]

## Suggested fix approach
- Update the workflow to:
  - Remove only `node_modules` (optional) but **keep** `yarn.lock`.
  - Prefer `yarn install --immutable` right after checkout/pull to ensure the lockfile matches the branch.
  - Only regenerate `yarn.lock` as a result of intentional remediation commands (`yarn up ...`, adding `resolutions`, etc.).
- If you still want a “full refresh” mode, document it as an explicit opt-in step, not the default.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removing yarn.lock is intentional, tested without removing it - produced false results due to stale resolutions. Clean install is needed for accurate analysis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Label for Approved PRs documentation Improvements or additions to documentation enhancement New feature or request jira/valid-reference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants