| 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 and the merge conflict 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.
{
"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):
"globalOverrides": {
"rollup-plugin-copy>globby": "^11.0.0",
"elliptic": "^6.6.1",
"fast-xml-parser": "^5.3.6",
"axios@<1.0.0": "^1.13.5",
"serialize-javascript": "^7.0.3"
}
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.
{
"unsupportedPackageJsonSettings": {
"pnpm": {
"auditConfig": {
"ignoreCves": [
"CVE-XXXX-XXXXX"
]
}
}
}
}
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
- Update the version range in the affected
package.json
- Run
rush update then rush audit to verify
- If no safe version range exists, fall through to globalOverride (document why)
2b. Transitive Dependency Fix
- 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.
- 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
- 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:
rush update
rush audit
rush build
rush test
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:
rush extract-api
Skip extract-api only when the sole change is a globalOverride in pnpm-config.json.
Rush Change Files
After remediation, Rush requires changelog entries:
rush change --verify -b origin/<base-branch>
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.