- name
- cve-remediation
- description
- Domain knowledge for remediating CVEs in the iTwin.js Rush monorepo — pnpm-config.json structure, fix strategies, validation, and audit workflows.
# 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.
Voir sur GitHub