From afcefd934dc82abc3d6563a17b9d7913378d1a93 Mon Sep 17 00:00:00 2001 From: Eric Cornelissen Date: Sat, 10 Feb 2024 17:25:12 +0100 Subject: [PATCH] feat: add --integrity-exclude option Add a new option available on the CLI as --integrity-exclude which allows user to disable the --validate-integrity check for specific packages.As an aside, this also formats the table in the lockfile-lint package's README. fix #187 --- .../validators.integrityHashType.test.js | 29 ++++++++++++++++++- .../src/validators/ValidateIntegrity.js | 15 +++++++--- packages/lockfile-lint/README.md | 23 ++++++++------- packages/lockfile-lint/bin/lockfile-lint.js | 3 +- packages/lockfile-lint/src/config.js | 4 +++ .../lockfile-lint/src/validators/index.js | 2 +- 6 files changed, 58 insertions(+), 18 deletions(-) diff --git a/packages/lockfile-lint-api/__tests__/validators.integrityHashType.test.js b/packages/lockfile-lint-api/__tests__/validators.integrityHashType.test.js index fe3dc9b..dde6c51 100644 --- a/packages/lockfile-lint-api/__tests__/validators.integrityHashType.test.js +++ b/packages/lockfile-lint-api/__tests__/validators.integrityHashType.test.js @@ -17,6 +17,15 @@ describe('Validator: Integrity', () => { expect(() => new ValidateIntegrity()).toThrowError() }) + it('validator should throw an error when excludedPackages is not an array', () => { + const options = { + integrityExclude: 'not-an-array' + } + + const validator = new ValidateIntegrity({packages: {}}) + expect(() => validator.validate(options)).toThrowError() + }) + it('validator should fail if not allowed hash type is used for a resource', () => { const mockedPackages = { bolt11: { @@ -29,7 +38,8 @@ describe('Validator: Integrity', () => { type: 'error', errors: [ { - message: 'detected invalid integrity hash type for package: bolt11\n expected: sha512\n actual: sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg=\n', + message: + 'detected invalid integrity hash type for package: bolt11\n expected: sha512\n actual: sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg=\n', package: 'bolt11' } ] @@ -71,6 +81,23 @@ describe('Validator: Integrity', () => { }) }) + it('validator should not fail if an excluded package has an invalid integrity hash type', () => { + const mockedPackages = { + typescript: { + integrity: 'sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg=' + } + } + const options = { + integrityExclude: ['typescript'] + } + + const validator = new ValidateIntegrity({packages: mockedPackages}) + expect(validator.validate(options)).toEqual({ + type: 'success', + errors: [] + }) + }) + it('validator should return true for a single package with a valid URL', () => { const mockedPackages = { typescript: { diff --git a/packages/lockfile-lint-api/src/validators/ValidateIntegrity.js b/packages/lockfile-lint-api/src/validators/ValidateIntegrity.js index 9ea616f..f539683 100644 --- a/packages/lockfile-lint-api/src/validators/ValidateIntegrity.js +++ b/packages/lockfile-lint-api/src/validators/ValidateIntegrity.js @@ -13,7 +13,12 @@ module.exports = class ValidateIntegrity { this.packages = packages } - validate () { + validate (options) { + const excludedPackages = options && options.integrityExclude ? options.integrityExclude : [] + if (!Array.isArray(excludedPackages)) { + throw new Error('excluded packages must be an array') + } + const validationResult = { type: 'success', errors: [] @@ -24,12 +29,14 @@ module.exports = class ValidateIntegrity { continue } + if (excludedPackages.includes(packageName)) { + continue + } + try { if (!isSha512(packageMetadata)) { validationResult.errors.push({ - message: `detected invalid integrity hash type for package: ${packageName}\n expected: sha512\n actual: ${ - packageMetadata.integrity - }\n`, + message: `detected invalid integrity hash type for package: ${packageName}\n expected: sha512\n actual: ${packageMetadata.integrity}\n`, package: packageName }) } diff --git a/packages/lockfile-lint/README.md b/packages/lockfile-lint/README.md index c54ab8c..4d6ce48 100644 --- a/packages/lockfile-lint/README.md +++ b/packages/lockfile-lint/README.md @@ -78,17 +78,18 @@ lockfile-lint --path yarn.lock --allowed-hosts yarn --allowed-urls https://githu | command line argument | description | implemented | |----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------| -| `--path`, `-p` | path to the lockfile but you can also provide a glob matching pattern as long as it isn't expanded by a shell like bash or zsh. If that's the case, you can provide it as a string, for example: `-p '/Users/lirantal/repos/**/package-lock.json'` to match multiple lockfiles | ✅ | -| `--type`, `-t` | lockfile type, options are `npm` or `yarn` | ✅ | -| `--format`, `-f` | sets what type of report output is desired, one of [ `pretty`, `plain` ] with `plain` removing colors & status symbols from output | ✅ | -| `--validate-https`, `-s` | validates the use of HTTPS as protocol schema for all resources in the lockfile | ✅ | -| `--allowed-hosts`, `-a` | validates a list of allowed hosts to be used for all resources in the lockfile. Supported short-hands aliases are `npm`, `yarn`, and `verdaccio` which will match URLs `https://registry.npmjs.org`, `https://registry.yarnpkg.com` and `https://registry.verdaccio.org` respectively | ✅ | -| `--allowed-schemes`, `-o` | allowed [URI schemes](https://tools.ietf.org/html/rfc2396#section-3.1) such as "https:", "http", "git+ssh:", or "git+https:" | ✅ | -| `--allowed-urls`, `-u` | allowed URLs (e.g. `https://github.com/some-org/some-repo#some-hash`) | ✅ | -| `--empty-hostname`, `-e` | allow empty hostnames, or set to false if you wish for a stricter policy | ✅ | -| `--validate-package-names`, `-n` | validates that the resolved URL matches the package name | ✅ | -| `--validate-integrity`, `-i` | validates the integrity field is a sha512 hash | ✅ | -| `--allowed-package-name-aliases`, `-l` | allow package name aliases to be used by specifying package name and their alias as pairs (e.g: `string-width-cjs:string-width`) | ✅ | +| `--path`, `-p` | path to the lockfile but you can also provide a glob matching pattern as long as it isn't expanded by a shell like bash or zsh. If that's the case, you can provide it as a string, for example: `-p '/Users/lirantal/repos/**/package-lock.json'` to match multiple lockfiles | ✅ | +| `--type`, `-t` | lockfile type, options are `npm` or `yarn` | ✅ | +| `--format`, `-f` | sets what type of report output is desired, one of [ `pretty`, `plain` ] with `plain` removing colors & status symbols from output | ✅ | +| `--validate-https`, `-s` | validates the use of HTTPS as protocol schema for all resources in the lockfile | ✅ | +| `--allowed-hosts`, `-a` | validates a list of allowed hosts to be used for all resources in the lockfile. Supported short-hands aliases are `npm`, `yarn`, and `verdaccio` which will match URLs `https://registry.npmjs.org`, `https://registry.yarnpkg.com` and `https://registry.verdaccio.org` respectively | ✅ | +| `--allowed-schemes`, `-o` | allowed [URI schemes](https://tools.ietf.org/html/rfc2396#section-3.1) such as "https:", "http", "git+ssh:", or "git+https:" | ✅ | +| `--allowed-urls`, `-u` | allowed URLs (e.g. `https://github.com/some-org/some-repo#some-hash`) | ✅ | +| `--empty-hostname`, `-e` | allow empty hostnames, or set to false if you wish for a stricter policy | ✅ | +| `--validate-package-names`, `-n` | validates that the resolved URL matches the package name | ✅ | +| `--validate-integrity`, `-i` | validates the integrity field is a sha512 hash | ✅ | +| `--allowed-package-name-aliases`, `-l` | allow package name aliases to be used by specifying package name and their alias as pairs (e.g: `string-width-cjs:string-width`) | ✅ | +| `--integrity-exclude` | exclude packages from the `--validate-integrity` check | ✅ | # File-Based Configuration diff --git a/packages/lockfile-lint/bin/lockfile-lint.js b/packages/lockfile-lint/bin/lockfile-lint.js index dfdec9b..b183236 100755 --- a/packages/lockfile-lint/bin/lockfile-lint.js +++ b/packages/lockfile-lint/bin/lockfile-lint.js @@ -81,7 +81,8 @@ for (const lockfilePath of lockfilesList) { emptyHostname: config['empty-hostname'], allowedHosts: config['allowed-hosts'], allowedUrls: config['allowed-urls'], - allowedPackageNameAliases: config['allowed-package-name-aliases'] + allowedPackageNameAliases: config['allowed-package-name-aliases'], + integrityExclude: config['integrity-exclude'] } }) } diff --git a/packages/lockfile-lint/src/config.js b/packages/lockfile-lint/src/config.js index ccadc0e..ce26c52 100644 --- a/packages/lockfile-lint/src/config.js +++ b/packages/lockfile-lint/src/config.js @@ -85,6 +85,10 @@ module.exports = (argv, exitProcess = false, searchFrom = process.cwd()) => { type: 'array', describe: 'validates an alias of package names to be used for resources in the lockfile' }, + 'integrity-exclude': { + type: 'array', + describe: 'do not validate integrity for these package' + }, format: { alias: ['f'], type: 'string', diff --git a/packages/lockfile-lint/src/validators/index.js b/packages/lockfile-lint/src/validators/index.js index 2d5f7e6..ff780de 100644 --- a/packages/lockfile-lint/src/validators/index.js +++ b/packages/lockfile-lint/src/validators/index.js @@ -134,5 +134,5 @@ function ValidateIntegrityManager ({path, type, validatorValues, validatorOption const lockfile = parser.parseSync() const validator = new ValidateIntegrity({packages: lockfile.object}) - return validator.validate() + return validator.validate(validatorOptions) }