|
| 1 | +--- |
| 2 | +name: fix-security-issues |
| 3 | +description: Audit and remediate dependency security advisories while respecting package age policy, removing unused vulnerable capabilities, deduplicating Yarn resolutions, and validating affected tooling. |
| 4 | +license: MIT |
| 5 | +--- |
| 6 | + |
| 7 | +# Fix security issues |
| 8 | + |
| 9 | +Use this skill for dependency vulnerability remediation, Dependabot alerts, |
| 10 | +Yarn audit findings, or security-driven package upgrades. |
| 11 | + |
| 12 | +## Read first |
| 13 | + |
| 14 | +1. Read the repository `AGENTS.md` and the owning workspaces' instructions. |
| 15 | +2. Inspect `package.json`, `.yarnrc.yml`, `yarn.lock`, package catalogs, |
| 16 | + resolutions, package extensions, and dynamic package extensions. |
| 17 | +3. Inspect `.github/dependabot.yml` and any repository-specific package age, |
| 18 | + cooldown, registry, or release policy. |
| 19 | +4. Inspect the declared scripts for every affected workspace before choosing |
| 20 | + validation commands. |
| 21 | + |
| 22 | +Do not edit `yarn.lock` manually. Change the owning manifest, catalog, |
| 23 | +resolution, preset, or extension and let Yarn regenerate the graph. |
| 24 | + |
| 25 | +## Inventory the complete problem |
| 26 | + |
| 27 | +Start with the full recursive audit rather than a partial summary: |
| 28 | + |
| 29 | +```bash |
| 30 | +yarn npm audit --all --recursive --json --no-deprecations |
| 31 | +``` |
| 32 | + |
| 33 | +Normalize the output by severity, package, installed version, advisory, and |
| 34 | +dependent. For every finding: |
| 35 | + |
| 36 | +1. Read the advisory and identify the first patched version, affected |
| 37 | + functions, exploit preconditions, and whether a patch exists. |
| 38 | +2. Run `yarn why <package>` to find every path. A fixed direct path does not |
| 39 | + help if a stale compatible transitive path remains. |
| 40 | +3. Search repository source and installed dependent source to determine |
| 41 | + whether the vulnerable capability is used at runtime, only used by tooling, |
| 42 | + or unused. |
| 43 | +4. Group duplicate advisories for the same package, but do not omit findings |
| 44 | + because one report calls them low priority. |
| 45 | + |
| 46 | +Treat critical and high findings as required fixes. Address moderate and low |
| 47 | +findings whenever a compatible, policy-eligible remediation exists. |
| 48 | + |
| 49 | +## Enforce the package age policy |
| 50 | + |
| 51 | +Before resolving versions, inspect the effective Yarn policy: |
| 52 | + |
| 53 | +```bash |
| 54 | +yarn config get npmMinimalAgeGate |
| 55 | +yarn config get npmPreapprovedPackages |
| 56 | +``` |
| 57 | + |
| 58 | +Calculate the exact cutoff from the session time. Verify publication timestamps |
| 59 | +for proposed versions and, after lockfile generation, every newly selected npm |
| 60 | +version in the lockfile diff. |
| 61 | + |
| 62 | +- Do not disable or reduce the age gate to obtain a security fix. |
| 63 | +- Do not assume `latest` is eligible. |
| 64 | +- Check preapproved-package exceptions explicitly; an exception does not prove |
| 65 | + that a newly selected release meets the requested age policy. |
| 66 | +- Prefer the newest eligible fixed patch within the existing compatible range, |
| 67 | + not the newest package release overall. |
| 68 | + |
| 69 | +## Choose the least risky complete remediation |
| 70 | + |
| 71 | +Use this order: |
| 72 | + |
| 73 | +1. **Upgrade the direct dependency.** Prefer a patched version within the |
| 74 | + current major and update the shared catalog when it is the source of truth. |
| 75 | +2. **Upgrade the transitive parent.** This is preferable when the parent has |
| 76 | + already adopted the fixed dependency. |
| 77 | +3. **Add a narrow root resolution.** Use the exact vulnerable descriptor when |
| 78 | + possible. Review API and module-format compatibility before forcing a new |
| 79 | + major, and exercise the dependent package's real code path. |
| 80 | +4. **Remove an unused vulnerable capability with `ignore:`.** Use the installed |
| 81 | + `@rnx-kit/yarn-plugin-ignore` only after proving the package is not required |
| 82 | + by repository workflows. |
| 83 | +5. **Carry a local Yarn patch.** Reserve this for required packages with no |
| 84 | + eligible published fix. Base it on authoritative upstream work, add a |
| 85 | + focused regression check, and document that version-based scanners may |
| 86 | + still report the patched version. |
| 87 | + |
| 88 | +Do not add a broad catch, audit exclusion, or warning suppression in place of a |
| 89 | +runtime fix. |
| 90 | + |
| 91 | +## Safely use the ignore plugin |
| 92 | + |
| 93 | +The repository's `ignore:` protocol replaces a package with an empty module. |
| 94 | +It is appropriate when a transitive dependency implements an optional |
| 95 | +capability that this repository intentionally does not support, such as a |
| 96 | +browser downloader in a native-only test path. |
| 97 | + |
| 98 | +Before adding a resolution such as: |
| 99 | + |
| 100 | +```json |
| 101 | +{ |
| 102 | + "resolutions": { |
| 103 | + "unused-vulnerable-package": "ignore:" |
| 104 | + } |
| 105 | +} |
| 106 | +``` |
| 107 | + |
| 108 | +prove all of the following: |
| 109 | + |
| 110 | +- no repository source imports or invokes the package; |
| 111 | +- each dependent imports it lazily or can load with an empty module; |
| 112 | +- the unsupported capability fails closed if invoked; |
| 113 | +- declared builds, tests, bundles, and CLIs do not require it; |
| 114 | +- `yarn why` shows only the understood optional paths. |
| 115 | + |
| 116 | +After installation, verify the npm package is absent from `yarn.lock`, the |
| 117 | +`ignore:` locator is present, dependent modules still load, and an attempted |
| 118 | +call cannot silently succeed. Never ignore a package merely to make the audit |
| 119 | +output clean. |
| 120 | + |
| 121 | +## Resolve, audit, and deduplicate iteratively |
| 122 | + |
| 123 | +After each coherent manifest change: |
| 124 | + |
| 125 | +```bash |
| 126 | +yarn install |
| 127 | +yarn npm audit --all --recursive --json --no-deprecations |
| 128 | +yarn why <remaining-vulnerable-package> |
| 129 | +``` |
| 130 | + |
| 131 | +Yarn may retain an older resolution that still satisfies a transitive range, |
| 132 | +even when a fixed version is also installed. Once the remediation set is |
| 133 | +complete, run: |
| 134 | + |
| 135 | +```bash |
| 136 | +yarn dedupe --strategy highest |
| 137 | +yarn dedupe --check |
| 138 | +yarn install --immutable --mode=skip-build |
| 139 | +``` |
| 140 | + |
| 141 | +Re-run the audit after dedupe. If stale vulnerable paths remain, update their |
| 142 | +owning range or add a narrow compatible resolution; do not assume another |
| 143 | +dedupe pass will update a package with only one descriptor. |
| 144 | + |
| 145 | +Keep related package families aligned. If repository lint expects an older |
| 146 | +vulnerable version, update the shared alignment preset or catalog rather than |
| 147 | +scattering exceptions or reverting the security floor. |
| 148 | + |
| 149 | +## Validate the affected behavior |
| 150 | + |
| 151 | +Use declared workspace scripts and validate in increasing scope: |
| 152 | + |
| 153 | +1. Format changed manifests and configuration. |
| 154 | +2. Run lockfile and repository structural lint. |
| 155 | +3. Run affected workspace lint, build, and tests. |
| 156 | +4. Exercise the runtime path affected by every major-version resolution. |
| 157 | +5. Bundle each affected Metro/native target when bundler dependencies change. |
| 158 | +6. Run the root build and repository test graph when shared manifests, |
| 159 | + catalogs, resolutions, or the lockfile change broadly. |
| 160 | +7. Add a normal or empty changeset as required by repository policy. |
| 161 | + |
| 162 | +Finish by confirming: |
| 163 | + |
| 164 | +- the recursive audit has no unexplained findings; |
| 165 | +- every critical/high advisory is fixed, removed, or blocked fail-closed; |
| 166 | +- newly selected npm versions satisfy the exact package age cutoff; |
| 167 | +- `yarn dedupe --check` reports no candidates; |
| 168 | +- immutable install succeeds; |
| 169 | +- the diff contains no unrelated manifest or generated-file changes. |
| 170 | + |
| 171 | +## Failure behavior |
| 172 | + |
| 173 | +If a required package has no eligible patched release, cannot be safely |
| 174 | +ignored, and cannot be patched with a focused regression test, report the |
| 175 | +remaining advisory and its exposure plainly. Do not claim completion, weaken |
| 176 | +the age policy, force an unvalidated incompatible major, or suppress the |
| 177 | +warning. |
| 178 | + |
| 179 | +## Example |
| 180 | + |
| 181 | +If `extract-zip` is present only through optional browser installation code |
| 182 | +while the repository runs native Appium automation, inspect both dependents, |
| 183 | +confirm their normal modules load without extraction, resolve `extract-zip` to |
| 184 | +`ignore:`, regenerate and deduplicate the lockfile, then prove the browser |
| 185 | +archive path fails closed and the native tooling still works. |
0 commit comments