# Cve Remediation

> Domain knowledge for remediating CVEs in the iTwin.js Rush monorepo — pnpm-config.json structure, fix strategies, validation, and audit workflows.

- Skill: `itwin/cve-remediation` (Agent Skill)
- Install (CLI): `npx skillmds@latest add itwin/cve-remediation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/itwin/cve-remediation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: itwin (https://skillmd.com/u/itwin)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/itwin/cve-remediation

---


# CVE Remediation in iTwin.js

This skill covers the domain knowledge for fixing security vulnerabilities in the iTwin.js Rush monorepo. It is referenced by the CVE audit agent, the `merge-conflict-resolving` skill, and the `backport-resolution` skill.

## Key Files

| File | Purpose |
| --- | --- |
| `common/config/rush/pnpm-config.json` | Global dependency overrides and audit exceptions |
| `common/config/rush/pnpm-lock.yaml` | Resolved dependency tree (never manually edit) |
| `common/config/rush/common-versions.json` | Rush version-consistency policy (`preferredVersions`) |
| `common/config/rush/repo-state.json` | Auto-generated hash of repo state (commit alongside `common-versions.json`) |
| `<package>/package.json` | Direct dependency version ranges per package |

## pnpm-config.json Structure

This file has two conflict-prone sections:

### globalOverrides

Forces specific dependency versions across the entire monorepo. Used when a transitive dependency cannot be updated via its parent's semver range.

```json
{
  "globalOverrides": {
    "<package>": "<patched-version>",
    "<package>@<range>": "<patched-version>"
  }
}
```

Each override should include a trailing comment with:
- The advisory URL (GHSA or CVE link)
- The dependency path that pulls in the vulnerable package

Illustrative example (always consult the current `common/config/rush/pnpm-config.json` before editing):

```jsonc
"globalOverrides": {
  "rollup-plugin-copy>globby": "^11.0.0", // https://github.com/vladshcherbin/rollup-plugin-copy/issues/77
  "elliptic": "^6.6.1", // https://github.com/advisories/GHSA-vjh7-7g9h-fjfh crypto-browserify>browserify-sign>elliptic
  "fast-xml-parser": "^5.3.6", // https://github.com/advisories/GHSA-jmr7-xgp7-cmfj @google-cloud/storage > fast-xml-parser
  "axios@<1.0.0": "^1.13.5", // https://github.com/advisories/GHSA-43fc-jf86-j433
  "serialize-javascript": "^7.0.3" // https://github.com/advisories/GHSA-5c6j-r48x-rmvq mocha>serialize-javascript
}
```

**Important:** This file uses JSONC (JSON with comments). The last entry in any object/array must NOT have a trailing comma. When adding entries, ensure the previously-last entry gets a comma added and the new last entry does not have one.

### ignoreCves (Audit Exceptions)

Located under a nested path. Used only for dev-tooling dependencies with no production path.

```json
{
  "unsupportedPackageJsonSettings": {
    "pnpm": {
      "auditConfig": {
        "ignoreCves": [
          "CVE-XXXX-XXXXX" // https://advisory-url — dev-only reason
        ]
      }
    }
  }
}
```

## Fix Strategy (Strict Order)

Always attempt fixes in this order. Do not skip to overrides without trying the earlier steps.

### 1. Classify: Direct vs Transitive

- **Direct:** The vulnerable package is listed in a project's `package.json`
- **Transitive:** The vulnerable package is pulled in by another dependency

### 2a. Direct Dependency Fix

1. Update the version range in the affected `package.json`
2. Run `rush update` then `rush audit` to verify
3. If no safe version range exists, fall through to globalOverride (document why)

### 2b. Transitive Dependency Fix

1. **Check existing overrides first:** Before adding a new override, check if the package already has an entry in `globalOverrides` in `pnpm-config.json` to avoid conflicts or duplicates.
2. **Semver range update (try first):** Update the direct parent's `package.json` range to a version that resolves the transitive dep to a patched release
3. **Scoped globalOverride (last resort):** Only if no safe parent version exists. Scope the override to only the vulnerable version range (e.g., `"lodash@>=4.0.0 <=4.17.23": "^4.18.0"`) rather than overriding all versions blanket. This avoids interfering with future already-patched versions. Document why in the override comment.

Use `rush-pnpm why <package>` to trace transitive dependency paths when the audit output truncates them.

### 3. ignoreCves (Absolute Last Resort)

Only for non-production/dev-tooling risk. Requires:
- Explicit rationale in comment
- Advisory link
- Confirmation that the dependency has no production code path

**Never ignore a Critical/High production-path CVE when a patch is available.**

## Severity Policy

| Severity | Action |
| --- | --- |
| Critical | Always fix or explicitly document blocker and risk |
| High | Fix unless unacceptable breakage; if deferred, create tracking issue |
| Moderate/Low | Defer and create tracking issue with recommendation |

## Validation Workflow

After any remediation change:

```bash
rush update                # Regenerate lock file
rush audit                 # Verify CVE is resolved (internally runs rush-pnpm audit --audit-level high)
rush build                 # Ensure no build breakage
rush test                  # Ensure no test regressions
```

**Note:** `rush audit` does not accept `--level` or `--json` flags directly. Use `rush-pnpm why <package>` to investigate specific dependency paths.

When direct dependency version ranges were changed in a `package.json`:

```bash
rush extract-api           # Check for API surface changes
```

Skip `extract-api` only when the sole change is a `globalOverride` in `pnpm-config.json`.

## Rush Change Files

After remediation, Rush requires changelog entries:

```bash
# Check if change files are needed
rush change --verify -b origin/<base-branch>

# If needed for internal dependency-only updates, create blank entries non-interactively
rush change --bulk --message "" --bump-type none -b origin/<base-branch>
```

Change files land in `common/changes/@itwin/<package>/` as JSON files with unique filenames.

## common-versions.json

If a direct dependency bump triggers Rush consistency errors, update `common/config/rush/common-versions.json` to align versions. Always commit the auto-generated `common/config/rush/repo-state.json` hash update alongside it.

