Repository: lirantal/lockfile-lint
Pull request #135 (2022-09-10 16:15:33)

Feature: Integrity hash type validator
<!--- Provide a general summary of your changes in the Title above -->

## Description

Added a new validator to check that the integrity field uses sha512 hash.  
Requires a flag `--validate-integrity` (alias: `-i`) so should not be a breaking change.

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Related Issue

<!--- This project only accepts pull requests related to open issues -->
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->

## Motivation and Context

<!--- Why is this change required? What problem does it solve? -->

## How Has This Been Tested?

<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->
<!--- Unit tests are expected for all changes. -->

Wrote unit tests.  
Also, tested on a real package-lock.json file that contains `sha1`

## Screenshots (if appropriate):

## Checklist:

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] I have updated the documentation (if required).
- [x] I have read the **CONTRIBUTING** document.
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.
- [ ] I added a picture of a cute animal cause it's fun


lirantal: This is awesome Yoav. I'm traveling to Open Source Summit this week so a bit low on availability but will review shortly!
codecov-commenter: # [Codecov](https://codecov.io/gh/lirantal/lockfile-lint/pull/135?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal) Report
Base: **97.75**% // Head: **95.90**% // Decreases project coverage by **`-1.84%`** :warning:
> Coverage data is based on head [(`9a14afa`)](https://codecov.io/gh/lirantal/lockfile-lint/pull/135?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal) compared to base [(`4667c3d`)](https://codecov.io/gh/lirantal/lockfile-lint/commit/4667c3d1e41097adba95e805cff98fed4a07297c?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal).
> Patch coverage: 77.41% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #135      +/-   ##
==========================================
- Coverage   97.75%   95.90%   -1.85%     
==========================================
  Files          12       13       +1     
  Lines         312      342      +30     
  Branches       67       73       +6     
==========================================
+ Hits          305      328      +23     
- Misses          7       14       +7     
```


| [Impacted Files](https://codecov.io/gh/lirantal/lockfile-lint/pull/135?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal) | Coverage Δ | |
|---|---|---|
| [packages/lockfile-lint/src/config.js](https://codecov.io/gh/lirantal/lockfile-lint/pull/135/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal#diff-cGFja2FnZXMvbG9ja2ZpbGUtbGludC9zcmMvY29uZmlnLmpz) | `100.00% <ø> (ø)` | |
| [packages/lockfile-lint/src/main.js](https://codecov.io/gh/lirantal/lockfile-lint/pull/135/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal#diff-cGFja2FnZXMvbG9ja2ZpbGUtbGludC9zcmMvbWFpbi5qcw==) | `100.00% <ø> (ø)` | |
| [packages/lockfile-lint/src/validators/index.js](https://codecov.io/gh/lirantal/lockfile-lint/pull/135/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal#diff-cGFja2FnZXMvbG9ja2ZpbGUtbGludC9zcmMvdmFsaWRhdG9ycy9pbmRleC5qcw==) | `73.07% <12.50%> (-11.37%)` | :arrow_down: |
| [packages/lockfile-lint-api/index.js](https://codecov.io/gh/lirantal/lockfile-lint/pull/135/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal#diff-cGFja2FnZXMvbG9ja2ZpbGUtbGludC1hcGkvaW5kZXguanM=) | `100.00% <100.00%> (ø)` | |
| [...kfile-lint-api/src/validators/ValidateIntegrity.js](https://codecov.io/gh/lirantal/lockfile-lint/pull/135/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal#diff-cGFja2FnZXMvbG9ja2ZpbGUtbGludC1hcGkvc3JjL3ZhbGlkYXRvcnMvVmFsaWRhdGVJbnRlZ3JpdHkuanM=) | `100.00% <100.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/lirantal/lockfile-lint/pull/135?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Liran+Tal).

lirantal: Besides the comments, note the coverage miss.
lirantal: @yoavain looks good.
one last check before we land this, with regards to [this comment](https://github.com/lirantal/lockfile-lint/pull/135#discussion_r973628179):
> To be more precise we're not validating the integrity itself here but rather it's type, so wdyt about updating the flag and naming convention to be explicit about the type validate-integrity-sha256 ?

Do you think it's better to leave this as `validate-integrity` rather than call out that we're strictly checking the type conforms to a good type?

yoavain: I think that as you said, we're not actually testing the validity, only the type.
How about `--validate-integrity-type`? This sounds more generic and will allow changing the "recommended" types in the future.
lirantal: I'm pretty open about this. As in, we could also keep it as is with `--validate-integrity`, and in the future add an actual integrity check on the data itself to validate that the signature hasn't been spoofed.
lirantal: Yep, let's do that and land this. In the meanwhile, open for others to chime in on this thread or a new issue and suggest as need.

Patch:
diff --git a/packages/lockfile-lint-api/README.md b/packages/lockfile-lint-api/README.md
index b6f8112..b368dd4 100644
--- a/packages/lockfile-lint-api/README.md
+++ b/packages/lockfile-lint-api/README.md
@@ -35,11 +35,12 @@ npm install --save lockfile-lint-api
 The following lockfile validators are supported
 
 | Validator API        | description                                                                     | implemented |
-| -------------------- | ------------------------------------------------------------------------------- | ----------- |
+|----------------------|---------------------------------------------------------------------------------| ----------- |
 | ValidateHttps        | validates the use of HTTPS as protocol schema for all resources                 | ✅          |
 | ValidateHost         | validates a whitelist of allowed hosts to be used for resources in the lockfile | ✅          |
 | ValidatePackageNames | validates that the resolved URL matches the package name                        | ✅          |
 | ValidateScheme       | validates a whitelist of allowed URI schemes to be used for hosts               | ✅          |
+| ValidateIntegrity    | validates that the integrity hash type is sha512                                | ✅          |
 
 **NOTE:** package entries without a `resolved` field (for example, those installed from the local filesystem) will automatically pass all url-based validators.
 
diff --git a/packages/lockfile-lint-api/index.js b/packages/lockfile-lint-api/index.js
index b6e8b97..6cfbf80 100644
--- a/packages/lockfile-lint-api/index.js
+++ b/packages/lockfile-lint-api/index.js
@@ -5,6 +5,7 @@ const ValidateHttps = require('./src/validators/ValidateHttps')
 const ValidatePackageNames = require('./src/validators/ValidatePackageNames')
 const ValidateScheme = require('./src/validators/ValidateScheme')
 const ValidateUrl = require('./src/validators/ValidateUrl')
+const ValidateIntegrity = require('./src/validators/ValidateIntegrity')
 const ParseLockfile = require('./src/ParseLockfile')
 
 module.exports = {
@@ -13,5 +14,6 @@ module.exports = {
   ValidateHttps,
   ValidatePackageNames,
   ValidateScheme,
-  ValidateUrl
+  ValidateUrl,
+  ValidateIntegrity
 }
diff --git a/packages/lockfile-lint-api/src/validators/ValidateIntegrity.js b/packages/lockfile-lint-api/src/validators/ValidateIntegrity.js
new file mode 100644
index 0000000..2ec358c
--- /dev/null
+++ b/packages/lockfile-lint-api/src/validators/ValidateIntegrity.js
@@ -0,0 +1,57 @@
+'use strict'
+
+function isSha512 (packageMetadata) {
+  return packageMetadata.integrity.split('-')[0] === 'sha512'
+}
+
+module.exports = class ValidateIntegrity {
+  constructor ({packages} = {}) {
+    if (typeof packages !== 'object') {
+      throw new Error('expecting an object passed to validator constructor')
+    }
+
+    this.packages = packages
+  }
+
+  validate () {
+    let validationResult = {
+      type: 'success',
+      errors: []
+    }
+
+    for (const [packageName, packageMetadata] of Object.entries(this.packages)) {
+      if (!('integrity' in packageMetadata)) {
+        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`,
+            package: packageName
+          })
+        }
+      } catch (error) {
+        // swallow error (assume that the integrity is valid)
+      }
+    }
+
+    if (validationResult.errors.length !== 0) {
+      validationResult.type = 'error'
+    }
+
+    return validationResult
+  }
+
+  validateSingle (packageName) {
+    // eslint-disable-next-line security/detect-object-injection
+    const packageMetadata = this.packages[packageName]
+    if (!('integrity' in packageMetadata)) {
+      return true
+    }
+
+    return isSha512(packageMetadata)
+  }
+}
diff --git a/packages/lockfile-lint/README.md b/packages/lockfile-lint/README.md
index 8a1aaab..2ec3ec9 100644
--- a/packages/lockfile-lint/README.md
+++ b/packages/lockfile-lint/README.md
@@ -76,19 +76,19 @@ lockfile-lint --path yarn.lock --allowed-hosts yarn --allowed-urls https://githu
 
 # CLI command options
 
-| command line argument            | description                                                                                                                                                                                                                                                                                | implemented    |
-| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- |
-| `--path`, `-p`                   | path to the lockfile                                                                                                                                                                                                                                                                       | ✅             |
-| `--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-checksum`, `-c`      | check that all resources include a checksum                                                                                                                                                                                                                                                | ❌ PRs welcome |
-| `--validate-integrity`, `-i`     | check that all resources include an integrity field                                                                                                                                                                                                                                        | ❌ PRs welcome |
+| command line argument                | description                                                                                                                                                                                                                                                                           | implemented   |
+|--------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
+| `--path`, `-p`                       | path to the lockfile                                                                                                                                                                                                                                                                  | ✅             |
+| `--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-checksum`, `-c`          | check that all resources include a checksum                                                                                                                                                                                                                                           | ❌ PRs welcome |
+| `--validate-integrity-sha512`, `-i`  | validates the integrity field is a sha512 hash                                                                                                                                                                                                                                        | ✅             |
 
 # File-Based Configuration
 
diff --git a/packages/lockfile-lint/bin/lockfile-lint.js b/packages/lockfile-lint/bin/lockfile-lint.js
index 4bbc5d0..a0ff0b6 100755
--- a/packages/lockfile-lint/bin/lockfile-lint.js
+++ b/packages/lockfile-lint/bin/lockfile-lint.js
@@ -44,7 +44,8 @@ const supportedValidators = new Map([
   ['validate-https', 'validateHttps'],
   ['validate-package-names', 'ValidatePackageNames'],
   ['allowed-schemes', 'validateSchemes'],
-  ['allowed-urls', 'validateUrls']
+  ['allowed-urls', 'validateUrls'],
+  ['validate-integrity-sha512', 'validateIntegrity']
 ])
 
 for (const [commandArgument, commandValue] of Object.entries(config)) {
diff --git a/packages/lockfile-lint/src/config.js b/packages/lockfile-lint/src/config.js
index 7564213..02613d7 100644
--- a/packages/lockfile-lint/src/config.js
+++ b/packages/lockfile-lint/src/config.js
@@ -52,6 +52,11 @@ module.exports = (argv, exitProcess = false, searchFrom = process.cwd()) => {
           "validates that the resource URL specifies the same package name as that listed as the lockfile entry's key",
         implies: 'allowed-hosts'
       },
+      i: {
+        alias: ['validate-integrity-sha512'],
+        type: 'boolean',
+        describe: 'validates that the integrity hash type is sha512'
+      },
       e: {
         alias: 'empty-hostname',
         type: 'boolean',
diff --git a/packages/lockfile-lint/src/main.js b/packages/lockfile-lint/src/main.js
index d1957c8..20ce8bc 100644
--- a/packages/lockfile-lint/src/main.js
+++ b/packages/lockfile-lint/src/main.js
@@ -6,7 +6,8 @@ const {
   ValidateHttpsManager,
   ValidatePackageNamesManager,
   ValidateSchemeManager,
-  ValidateUrlManager
+  ValidateUrlManager,
+  ValidateIntegrityManager
 } = require('../src/validators')
 
 const validatorFunctions = new Map([
@@ -14,7 +15,8 @@ const validatorFunctions = new Map([
   ['validateHttps', ValidateHttpsManager],
   ['ValidatePackageNames', ValidatePackageNamesManager],
   ['validateSchemes', ValidateSchemeManager],
-  ['validateUrls', ValidateUrlManager]
+  ['validateUrls', ValidateUrlManager],
+  ['validateIntegrity', ValidateIntegrityManager]
 ])
 
 function runValidators ({type, path, validators} = {}) {
diff --git a/packages/lockfile-lint/src/validators/index.js b/packages/lockfile-lint/src/validators/index.js
index bd12baa..197628a 100644
--- a/packages/lockfile-lint/src/validators/index.js
+++ b/packages/lockfile-lint/src/validators/index.js
@@ -6,7 +6,8 @@ const {
   ValidateHttps,
   ValidatePackageNames,
   ValidateScheme,
-  ValidateUrl
+  ValidateUrl,
+  ValidateIntegrity
 } = require('lockfile-lint-api')
 const debug = require('debug')('lockfile-lint')
 
@@ -15,7 +16,8 @@ module.exports = {
   ValidateHttpsManager,
   ValidatePackageNamesManager,
   ValidateSchemeManager,
-  ValidateUrlManager
+  ValidateUrlManager,
+  ValidateIntegrityManager
 }
 
 function ValidateSchemeManager ({path, type, validatorValues, validatorOptions}) {
@@ -113,3 +115,20 @@ function ValidateUrlManager ({path, type, validatorValues, validatorOptions}) {
 
   return validator.validate(validatorValues, validatorOptions)
 }
+
+function ValidateIntegrityManager ({path, type, validatorValues, validatorOptions}) {
+  debug(
+    `validate-integrity-manager invoked with validator options: ${JSON.stringify(validatorValues)}`
+  )
+
+  const options = {
+    lockfilePath: path,
+    lockfileType: type
+  }
+
+  const parser = new ParseLockfile(options)
+  const lockfile = parser.parseSync()
+  const validator = new ValidateIntegrity({packages: lockfile.object})
+
+  return validator.validate()
+}


Test patch:
diff --git a/packages/lockfile-lint-api/__tests__/validators.integrityHashType.test.js b/packages/lockfile-lint-api/__tests__/validators.integrityHashType.test.js
new file mode 100644
index 0000000..76d7483
--- /dev/null
+++ b/packages/lockfile-lint-api/__tests__/validators.integrityHashType.test.js
@@ -0,0 +1,105 @@
+const ValidateIntegrity = require('../src/validators/ValidateIntegrity')
+
+describe('Validator: Integrity', () => {
+  it('validator should throw an error when provided a string', () => {
+    expect(() => new ValidateIntegrity('ss')).toThrowError()
+  })
+
+  it('validator should throw an error when provided null', () => {
+    expect(() => new ValidateIntegrity(null)).toThrowError()
+  })
+
+  it('validator should throw an error when provided array', () => {
+    expect(() => new ValidateIntegrity(['a'])).toThrowError()
+  })
+
+  it('validator should throw an error instantiated with no value', () => {
+    expect(() => new ValidateIntegrity()).toThrowError()
+  })
+
+  it('validator should fail if not allowed hash type is used for a resource', () => {
+    const mockedPackages = {
+      bolt11: {
+        integrity: 'sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg='
+      }
+    }
+
+    const validator = new ValidateIntegrity({packages: mockedPackages})
+    expect(validator.validate()).toEqual({
+      type: 'error',
+      errors: [
+        {
+          message: `detected invalid integrity hash type for package: bolt11\n    expected: sha512\n    actual: sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg=\n`,
+          package: 'bolt11'
+        }
+      ]
+    })
+  })
+
+  it('validator should succeed if all resources are from an allowed hash type', () => {
+    const mockedPackages = {
+      '@types/node': {
+        integrity:
+          'sha512-CK2fnrQlIgKlCV3N2kM+Gznb5USlwA1KFX3rJVHmgVk6NJxFPuQ86pAcvKnu37IA4BGlSRz7sEE1lHL1aLZ/eQ=='
+      },
+      typescript: {
+        integrity:
+          'sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig=='
+      }
+    }
+
+    const validator = new ValidateIntegrity({packages: mockedPackages})
+    expect(validator.validate()).toEqual({
+      type: 'success',
+      errors: []
+    })
+  })
+
+  it('validator should not fail even if one of the packages has no `integrity` field', () => {
+    const mockedPackages = {
+      typescript: {
+        integrity:
+          'sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig=='
+      },
+      meow: {}
+    }
+    const validator = new ValidateIntegrity({packages: mockedPackages})
+
+    expect(validator.validate()).toEqual({
+      type: 'success',
+      errors: []
+    })
+  })
+
+  it('validator should return true for a single package with a valid URL', () => {
+    const mockedPackages = {
+      typescript: {
+        resolved:
+          'sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig=='
+      }
+    }
+    const validator = new ValidateIntegrity({packages: mockedPackages})
+
+    expect(validator.validateSingle('typescript')).toEqual(true)
+  })
+
+  it('validator should return false for a single package with an invalid integrity hash type', () => {
+    const mockedPackages = {
+      typescript: {
+        integrity: 'sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg='
+      }
+    }
+    const validator = new ValidateIntegrity({packages: mockedPackages})
+
+    expect(validator.validateSingle('typescript')).toEqual(false)
+  })
+
+  it('validator should return true for a single package that does not have integrity', () => {
+    const mockedPackages = {
+      meow: {}
+    }
+    const validator = new ValidateIntegrity({packages: mockedPackages})
+
+    expect(validator.validateSingle('meow')).toEqual(true)
+  })
+})
diff --git a/packages/lockfile-lint/__tests__/cli.test.js b/packages/lockfile-lint/__tests__/cli.test.js
index 471d883..94d4d4a 100644
--- a/packages/lockfile-lint/__tests__/cli.test.js
+++ b/packages/lockfile-lint/__tests__/cli.test.js
@@ -4,7 +4,7 @@ const path = require('path')
 // eslint-disable-next-line security/detect-child-process
 const childProcess = require('child_process')
 const cliExecPath = path.join(__dirname, '../bin/lockfile-lint.js')
-const {ValidateHostManager, ValidateUrlManager} = require('../src/validators/index')
+const {ValidateHostManager, ValidateUrlManager, ValidateIntegrityManager} = require('../src/validators/index')
 
 describe('CLI tests', () => {
   test('Running without parameters should display help', done => {
@@ -333,4 +333,22 @@ describe('Validator managers:', () => {
       ]
     })
   })
+  it('Integrity manager should return errors for lock file with packages with sha1 integrity', () => {
+    const result = ValidateIntegrityManager({
+      path: '__tests__/fixtures/package-lock-sha1.json',
+      type: 'npm',
+      validatorValues: ['https://github.com/LN-Zap/bolt11#0492874ea9ced4ab49bf0f59a62368687f147247']
+    })
+
+    expect(result).toEqual({
+      type: 'error',
+      errors: [
+        {
+          message:
+            'detected invalid integrity hash type for package: typescript@4.8.3-4b39c20edf186cd85bb485386ba7d48590c3bf0c\n    expected: sha512\n    actual: sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg=\n',
+          package: 'typescript@4.8.3-4b39c20edf186cd85bb485386ba7d48590c3bf0c'
+        }
+      ]
+    })
+  })
 })
diff --git a/packages/lockfile-lint/__tests__/fixtures/package-lock-sha1.json b/packages/lockfile-lint/__tests__/fixtures/package-lock-sha1.json
new file mode 100644
index 0000000..63560a4
--- /dev/null
+++ b/packages/lockfile-lint/__tests__/fixtures/package-lock-sha1.json
@@ -0,0 +1,37 @@
+{
+  "name": "test-integrity-validator",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "test-integrity-validator",
+      "version": "1.0.0",
+      "license": "ISC",
+      "devDependencies": {
+        "typescript": "4.8.3"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "4.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
+      "integrity": "sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg=",
+      "dev": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=4.2.0"
+      }
+    }
+  },
+  "dependencies": {
+    "typescript": {
+      "version": "4.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
+      "integrity": "sha1-1ZNEUixLxGSmWnMKxpUAf9tm3Yg=",
+      "dev": true
+    }
+  }
+}