UNPKG

yarn-audit-fix

Version:
370 lines (324 loc) 21.1 kB
<p align="center"> <a href="https://yarnpkg.com/"> <img alt="Yarn audit fix" src="https://github.com/antongolub/yarn-audit-fix/blob/master/img/yarn-audit-fix.png?raw=true?raw=true" width="546"> </a> </p> <h1 align="center"> yarn-audit-fix </h1> [![CI](https://github.com/antongolub/yarn-audit-fix/workflows/CI/badge.svg)](https://github.com/antongolub/yarn-audit-fix/actions) [![Maintainability](https://api.codeclimate.com/v1/badges/1ace18434c46fe1a47fe/maintainability)](https://codeclimate.com/github/antongolub/yarn-audit-fix/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/1ace18434c46fe1a47fe/test_coverage)](https://codeclimate.com/github/antongolub/yarn-audit-fix/test_coverage) [![Sonar](https://sonarcloud.io/api/project_badges/measure?project=antongolub_yarn-audit-fix&metric=alert_status)](https://sonarcloud.io/dashboard?id=antongolub_yarn-audit-fix) [![Known Vulnerabilities](https://snyk.io/test/github/antongolub/yarn-audit-fix/badge.svg)](https://snyk.io/test/github/antongolub/yarn-audit-fix) [![Downloads](https://img.shields.io/npm/dt/yarn-audit-fix)](https://www.npmjs.com/package/yarn-audit-fix) [![npm (tag)](https://img.shields.io/npm/v/yarn-audit-fix)](https://www.npmjs.com/package/yarn-audit-fix) The missing `yarn audit fix` - [Digest](#digest) - [Problem](#problem) - [Solution](#solution) - [Key features](#key-features) - [Getting started](#getting-started) - [Requirements](#requirements) - [Install](#install) - [CLI](#cli) - [ENV](#env) - [JS API](#js-api) - [Migration notes](#migration-notes) - [^10.0.0](#1000) - [^9.0.0](#900) - [^8.0.0](#800) - [^7.0.0](#700) - [^6.0.0](#600) - [^4.0.0](#400) - [⚠️ Troubleshooting](#troubleshooting) - [Contributing](#contributing) - [License](#license) ## Digest ### Problem 1. `yarn audit` detects vulnerabilities, but cannot fix them. Authors suggest using [Dependabot](https://dependabot.com/) or [Snyk](https://snyk.io/) for security patches. Well, it is very inconvenient in some situations, to say the least of it. The discussion: [yarn/issues/7075](https://github.com/yarnpkg/yarn/issues/7075). 2. `yarn audit` does not support custom (in-house, internal) registries. Here are the [issue](https://github.com/yarnpkg/yarn/issues/7012) & [PR](https://github.com/yarnpkg/yarn/pull/6484) which have not yet received the green light. ### Solution Fortunately, there are several workarounds: 1. Compose `npm audit fix` with lockfile converter (thanks to [Gianfranco P.](https://github.com/gianpaj), [stackoverflow/60878037](https://stackoverflow.com/a/60878037)). `yarn-audit-fix --flow=convert` just reproduces these steps with minimal changes. More details: [dev.to/yarn-audit-fix-workaround](https://dev.to/antongolub/yarn-audit-fix-workaround-i2a) 2. Fetch `yarn/npm audit --json` advisories and patch lockfile inners (kudos to [G. Kosev](https://github.com/spion), [code reference](https://github.com/hfour/yarn-audit-fix-ng/blob/main/src/index.ts)). `yarn-audit-fix --flow=patch`. Full description: [dev.to/yarn-audit-fix-for-yarn-2-berry](https://dev.to/antongolub/the-missing-yarn-audit-fix-for-yarn-2-berry-1p8) ### Key features * Works with Yarn 1 Classic & Yarn v2+ lockfiles (⚠️ experimental) * A couple of strategies to fix security issues * macOS / Linux / Windows support * CLI / JS API * TS and flow typings ## Getting started ### Requirements Node.js: `>=16.0.0` ### Install ```shell script $ yarn add yarn-audit-fix -D ``` or even better ``` npm_config_yes=true npx yarn-audit-fix ``` ### CLI <pre> $ yarn-audit-fix [--opts] <b>Preparing temp assets...</b> <b>Generating package-lock.json from yarn.lock...</b> <b>Applying npm audit fix...</b> <b>invoke</b> npm audit fix --package-lock-only added 14 packages, removed 195 packages and updated 1245 packages in 4.795s fixed 3 of 26 vulnerabilities in 1370 scanned packages 23 vulnerabilities required manual review and could not be updated <b>Updating yarn.lock from package-lock.json...</b> <b>invoke</b> yarn import info found npm package-lock.json, converting to yarn.lock warning synp > request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 warning tslint-config-qiwi > tslint-react@5.0.0: tslint-react is deprecated along with TSLint warning @qiwi/libdefkit > @types/read-pkg@5.1.0: This is a stub types definition. read-pkg provides its own type definitions, so you do not need this installed. ... success Saved lockfile. <b>invoke</b> yarn [1/4] 🔍 Resolving packages... success Already up-to-date. <b>Done</b> </pre> | Option | Description | Default | with `--flow=convert` only | |-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------------------------| | `--flow` | Define how `yarn.lock` is modified. `convert` — to compose `npm audit fix` with two-way lockfile conversion (legacy flow). `patch` — to directly inject audit json data | `patch` | | | `--audit-level` | Include a vulnerability with a level as defined or higher. Supported values: low, moderate, high, critical | `low` | | | `--cwd` | Current working dir | `process.cwd()` | | | `--dry-run` | Get an idea of what audit fix will do | | | | `--force` | Have audit fix install semver-major updates to toplevel dependencies, not just semver-compatible ones | `false` | | | `--help/-h` | Print help message | | | | `--legacy-peer-deps` | Accept an incorrect (potentially broken) deps resolution | | ✔ | | `--loglevel` | Set custom [log level](https://docs.npmjs.com/cli/v7/using-npm/config#loglevel) | | ✔ | | `--npm-path` | Switch to project's local **npm** version instead of system default. Or provide a custom path. `system / local / <custom path>` | `system` | | | `--only` | Set package [update scope](https://docs.npmjs.com/cli/v7/using-npm/config#only): `dev`/`prod` | | | | `--package-lock-only` | Run audit fix without modifying `node_modules`. Highly recommended to **enable**. | `true` | ✔ | | `--registry` | Custom registry url | | ✔ | | `--silent` | Disable log output | `false` | | | `--symlink` | Symlink type for `node_modules` ref | `junction` for Windows, `dir` otherwise | | | `--temp` | Directory for temporary assets | `<cwd>/node_modules/.cache/yarn-audit-fix` | | | `--verbose` | Switch log level to verbose/debug | `false` | | | `--exclude` | Array of glob patterns of packages to exclude from audit | | | | `--ignore` | Array of glob patterns of advisory IDs to ignore in the audit report | | | ### ENV All mentioned above CLI options can be replaced with the corresponding env variables with leading **YAF** prefix. For example: * `YAF_FORCE` equals `--force` * `YAF_ONLY=prod``--only=prod` ### JS API **yarn-audit-fix** is a naive and optimistic workaround, so it exposes all of its inners to give anybody a chance to tweak up and find a better steps combination. Typedoc: [https://antongolub.github.io/yarn-audit-fix/modules/](https://antongolub.github.io/yarn-audit-fix/modules/) ```ts import { run, runSync } from 'yarn-audit-fix' // NOTE actually it's promisified `run.sync` await run({ flow: 'patch', verbose: true }) // `runSync` is an alias for `run.sync` await runSync({ flow: 'patch', verbose: true }) ``` Build and run custom flows. ```ts import { clear, exit, patchLockfile, yarnInstall } from 'yarn-audit-fix' export const flow: TFlow = { main: [ [ 'Patching yarn.lock with audit data...', patchLockfile, (...args) => {console.log('Smth interesting:', ...args)}, yarnInstall, ], ['Done'], ], fallback: [['Failure!', exit]], } await run({}, flow) ``` ## Migration notes ### ^10.0.0 v10 bumps the pkg deps and requires NodeJS v14. ### ^9.0.0 v9 brings experimental Yarn 2+ lockfiles support, so the previous behaviour (when `yaf` parsing failure may be used to detect them) has been changed. ### ^8.0.0 From v8 the library does not contain **npm** dependency, so the system default is used instead. If necessary you can: * Install the required npm version and provide a custom path via [CLI](#cli) / [ENV](#env) / [JS API](#js-api) * Use a pinch of **npx** magic: `npm_config_yes=true YAF_NPM_PATH=local npx -p yarn-audit-fix -p npm@8 -c yarn-audit-fix` ### ^7.0.0 Following the deps, converted to ESM. So legacy `require` API has been dropped since v7.0.0. Use the shiny new `import` instead or try your luck with [esm-hook](https://www.npmjs.com/package/@qiwi/esm). CLI works as before. ```js // const {run} = require('yarn-audit-fix') turns into import {run} from 'yarn-audit-fix' ``` ### ^6.0.0 Default fix strategy [has been changed](https://github.com/antongolub/yarn-audit-fix/releases/tag/v6.0.0) to direct lockfile patching with `yarn audit --json` data. To use the previous _legacy_ flow, pass `--flow=convert` option to CLI. ### ^4.0.0 `--npm-v7` flag is redundant. From v4.0.0 package's own version of **npm** is used by default. But you're still able to invoke system default with `--npm-path=system` or define any custom `--npm-path=/another/npm/bin`. ## Troubleshooting ### DoS vulnerability for colors 1.4.x If you have installed yaf between 7...11 of Jan 2022 and ran it with `--flow=convert` option, you might see an endless garbage loop in stdout. The problem was caused by the transitive dep: `yarn-audit-fix → synp → colors@^1.4.0`. Reasons and details: [issues/218](https://github.com/antongolub/yarn-audit-fix/issues/218), [snykvuln/2331906](https://security.snyk.io/vuln/SNYK-JS-COLORS-2331906). How to fix? There are 3 ways: * Update yarn-audit-fix to `>=9.0.5` * Pin `colors` version in your lockfile to `1.4.0` * Reinstall yarn-audit-fix. It looks like npm has already removed the vulnerable versions of `colors` from the registry, 2022-01-11. ### yarn-audit-fix version x.x.x is out of date ``` npm_config_yes=true npx yarn-audit-fix --audit-level=moderate Runtime digest yarn-audit-fix version 4.3.6 is out of date. Install the latest 6.0.0 for better results ``` **npx** caches previously loaded packages, so you need one of: 1. Define version to load: `npm yarn-audit-fix@6.0.0` 2. Reset npx cache. For Mac/Linux: `rm -rf ~/.npm/_npx` ### yarn-audit-fix command not found After installation, the package may not be found. This is probably an issue with $PATH finding `node_modules/.bin` contents or smth like that ([npm/issues/957](https://github.com/npm/npm/issues/957)). A bit annoying, but it's easy to handle in several ways. * You're able to run the cmd through **yarn**: `yarn yarn-audit-fix`. * Simply invoke `node_modules/.bin/yarn-audit-fix` script. ### enoent: no such file or directory In some cases **npm audit fix** makes `node_modules` to become inconsistent. This is expected. **yarn** and **npm** organize the directory space slightly differently. ``` npm WARN rm not removing /Users/antongolub/projects/queuefy/node_modules/.cache/yarn-audit-fix/node_modules/npm/node_modules/.bin/node-gyp as it wasn't installed by /Users/antongolub/projects/queuefy/node_modules/.cache/yarn-audit-fix/node_modules/npm/node_modules/node-gyp npm WARN rm not removing /Users/antongolub/projects/queuefy/node_modules/.cache/yarn-audit-fix/node_modules/npm/node_modules/.bin/uuid as it wasn't installed by /Users/antongolub/projects/queuefy/node_modules/.cache/yarn-audit-fix/node_modules/npm/node_modules/uuid npm ERR! code ENOENT npm ERR! syscall chmod npm ERR! path /Users/antongolub/projects/queuefy/node_modules/.cache/yarn-audit-fix/node_modules/@qiwi/libdefkit/node_modules/flowgen/lib/cli/index.js npm ERR! errno -2 npm ERR! enoent ENOENT: no such file or directory, chmod '/Users/antongolub/projects/queuefy/node_modules/.cache/yarn-audit-fix/node_modules/@qiwi/libdefkit/node_modules/flowgen/lib/cli/index.js' npm ERR! enoent This is related to npm not being able to find a file. npm ERR! enoent npm ERR! /Users/antongolub/.npm/_logs/2020-08-23T07_09_26_924Z-debug.log { status: 254, signal: null, output: [ null, null, null ] ``` Let's try this workaround: 1. Restore the original `node_modules` state. `yarn --force` or `rm-rf node_modules && yarn`. 2. Apply `npx yarn-audit-fix --package-lock-only`. The last param should instruct **npm** not to modify `node_modules` contents. ### --force did not force the update The problem only concerns repositories with `workspaces` (monorepos). `npm audit fix --force` throws 1 status code and suggests running `npm audit fix --force`. This quite ironic behaviour is exactly what **npm** (arborist) [does now](https://github.com/npm/arborist/blob/5b550501f50d6489d7e5f7598a97a5cf4cc5cc8a/lib/arborist/build-ideal-tree.js#L373). ``` $$ yarn-audit-fix --force Preparing temp assets... Generating package-lock.json from yarn.lock... Applying npm audit fix... invoke /home/qwelias/.nvm/versions/node/v12.18.1/lib/node_modules/yarn-audit-fix/node_modules/.bin/npm audit fix --package-lock-only --force --prefix=/home/qwelias/prj/stuff/test-yarn-audit-fix/node_modules/.cache/yarn-audit-fix npm WARN using --force Recommended protections disabled. npm WARN audit Updating lodash to 4.17.20,which is outside your stated dependency range. npm WARN audit Manual fix required in linked project at ./packages/bar for lodash@<=4.17.18. npm WARN audit 'cd ./packages/bar' and run 'npm audit' for details. npm WARN audit Manual fix required in linked project at ./packages/foo for lodash@<=4.17.18. npm WARN audit 'cd ./packages/foo' and run 'npm audit' for details. up to date, audited 7 packages in 2s # npm audit report lodash <=4.17.18 Severity: high Prototype Pollution - https://npmjs.com/advisories/782 Prototype Pollution - https://npmjs.com/advisories/1065 fix available via `npm audit fix --force` Will install lodash@4.17.20, which is outside the stated dependency range packages/bar/node_modules/lodash packages/foo/node_modules/lodash 1 high severity vulnerability To address all issues, run: npm audit fix --force { status: 1, signal: null, output: [ null, null, null ], pid: 176019, stdout: null, stderr: null } ``` So you need, as the message says, to manually change the dependency versions. **npm@7** ~~is still in beta~~, perhaps this logic will be changed later. In some cases **npm@6** works better, so if you have such a version installed on your system, you may try: ```shell npx yarn-audit-fix --npm-path=system --flow=convert ``` You may also try to cast _the optimistic flags combo_ ```shell npx yarn-audit-fix --package-lock-only=false --force --legacy-peer-deps --flow=convert ``` Unfortunately, even this invocation may return something like: ```shell # npm audit report hosted-git-info <3.0.8 Severity: moderate Regular Expression Deinal of Service - https://npmjs.com/advisories/1677 No fix available node_modules/normalize-package-data/node_modules/hosted-git-info normalize-package-data 2.0.0 - 2.5.0 Depends on vulnerable versions of hosted-git-info node_modules/normalize-package-data meow 3.4.0 - 9.0.0 Depends on vulnerable versions of normalize-package-data Depends on vulnerable versions of read-pkg-up ``` **No fix available** just means that no fix available. If you still doubt the correctness of the output, you can check it by hand. ```shell npm i --package-lock-only npm audit fix --package-lock-only --force ``` Same response for alternative patching flow: ```shell npm_config_yes=true npx yarn-audit-fix --audit-level=moderate --flow=patch ``` ```shell Patching yarn.lock with audit data... invoke yarn audit --json --level moderate Can't find patched version that satisfies postcss@^7.0.0 in >=8.2.10 Can't find patched version that satisfies postcss@^7.0.1 in >=8.2.10 Can't find patched version that satisfies postcss@^7.0.27 in >=8.2.10 Can't find patched version that satisfies ws@^7.2.3 in >=6.2.2 <7.0.0 || >=7.4.6 Upgraded deps: <none> invoke yarn --update-checksums ``` Not everything can be repaired, alack. ### Cannot install package despite being on correct node version yarn-audit-fix is compatible with any NodeJS version which supports ESM, but the nested packages can define their own engine requirements. ```shell pkg-dir@7.0.0: The engine "node" is incompatible with this module. Expected version ">=14.16". Got "14.15.1" ``` The _recommended_ way is to update the runtime version. As a temporary workaround, you can simply pass `--ignore-engines` flag. ```shell yarn add yarn-audit-fix -D --ignore-engines ``` ### Response Code: 400 (Bad Request) In some cases **yarn npm audit** fails because the `yarn.lock` file contains a transitive dependency in unreadable format: ``` 'example-dependency': 'npm:example-dependency@1.0.0' ``` This will results in: ```shell invoke yarn npm audit --all --json --recursive ➤ YN0035: Bad Request ➤ YN0035: Response Code: 400 (Bad Request) ➤ YN0035: Request Method: POST ➤ YN0035: Request URL: https://registry.yarnpkg.com/-/npm/v1/security/audits/quick ``` https://github.com/yarnpkg/berry/issues/4117 A workaround is available using the `exclude` option: 1. Update project **yarn** to >=3.3.0 (lower version doesn't support this parameter for **yarn npm audit**). 2. Apply `npx yarn-audit-fix --exclude example-dependency`. This will cause **yarn** to ignore `example-dependency` while creating the audit report. ## Contributing Feel free to open any issues: bugs, feature requests or other questions. You're always welcome to suggest a PR. Just fork this repo, write some code, add some tests and push your changes. Any feedback is appreciated. ## License [MIT](./LICENSE)