npq 2.5.1 → 2.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,209 @@
1
+ jest.mock('pacote')
2
+ jest.mock('node-fetch')
3
+
4
+ const fetch = require('node-fetch')
5
+
6
+ const ProvenanceMarshall = require('../lib/marshalls/provenance.marshall')
7
+ const pacote = require('pacote')
8
+
9
+ describe('Provenance test suites', () => {
10
+ beforeEach(() => {
11
+ jest.clearAllMocks()
12
+ jest.resetAllMocks()
13
+ })
14
+
15
+ test('has the right title', async () => {
16
+ const testMarshall = new ProvenanceMarshall({
17
+ packageRepoUtils: {
18
+ getPackageInfo: (pkgInfo) => {
19
+ return new Promise((resolve) => {
20
+ resolve(pkgInfo)
21
+ })
22
+ }
23
+ }
24
+ })
25
+
26
+ expect(testMarshall.title()).toEqual('Verifying package provenance')
27
+ })
28
+
29
+ test('should successfully validate a package with verified attestations', async () => {
30
+ // Mock the response from fetch
31
+ const mockResponse = {
32
+ json: jest.fn().mockResolvedValue({
33
+ keys: [
34
+ {
35
+ key: 'publicKey1'
36
+ },
37
+ {
38
+ key: 'publicKey2'
39
+ }
40
+ ]
41
+ })
42
+ }
43
+ fetch.mockImplementationOnce(() => Promise.resolve(mockResponse))
44
+
45
+ pacote.manifest = jest.fn().mockResolvedValue({
46
+ name: 'packageName',
47
+ version: '1.0.0',
48
+ _attestations: {
49
+ url: 'https://registry.npmjs.org/-/npm/v1/attestations/pacote@17.0.4',
50
+ provenance: { predicateType: 'https://slsa.dev/provenance/v1' }
51
+ }
52
+ })
53
+
54
+ // Call the validate method with a package object
55
+ const pkg = {
56
+ packageName: 'packageName',
57
+ packageVersion: '1.0.0'
58
+ }
59
+
60
+ const testMarshall = new ProvenanceMarshall({
61
+ packageRepoUtils: {
62
+ getPackageInfo: (pkgInfo) => {
63
+ return new Promise((resolve) => {
64
+ resolve({
65
+ name: pkg.packageName,
66
+ version: pkg.packageVersion
67
+ })
68
+ })
69
+ },
70
+ parsePackageVersion: (pkgVersion) => {
71
+ return {
72
+ version: pkgVersion
73
+ }
74
+ }
75
+ }
76
+ })
77
+
78
+ // We assert that the validate method didn't throw an error,
79
+ // because the keys match the signature
80
+ await testMarshall.validate(pkg)
81
+
82
+ // Assert that the fetch method is called with the correct URL
83
+ // eslint-disable-next-line no-undef
84
+ expect(fetch).toHaveBeenCalledWith('https://registry.npmjs.org/-/npm/v1/keys')
85
+
86
+ // Assert that the pacote.manifest method is called with the correct arguments
87
+ expect(pacote.manifest).toHaveBeenCalledWith('packageName@1.0.0', {
88
+ verifyAttestations: true,
89
+ registry: 'https://registry.npmjs.org',
90
+ '//registry.npmjs.org/:_keys': [
91
+ {
92
+ key: 'publicKey1',
93
+ pemkey: '-----BEGIN PUBLIC KEY-----\npublicKey1\n-----END PUBLIC KEY-----'
94
+ },
95
+ {
96
+ key: 'publicKey2',
97
+ pemkey: '-----BEGIN PUBLIC KEY-----\npublicKey2\n-----END PUBLIC KEY-----'
98
+ }
99
+ ]
100
+ })
101
+ })
102
+
103
+ test('should throw an error if attestation verification fails and manifest() throws an error', async () => {
104
+ // Mock the response from fetch
105
+ const mockResponse = {
106
+ json: jest.fn().mockResolvedValue({
107
+ keys: [
108
+ {
109
+ key: 'publicKey1'
110
+ },
111
+ {
112
+ key: 'publicKey2'
113
+ }
114
+ ]
115
+ })
116
+ }
117
+ fetch.mockImplementationOnce(() => Promise.resolve(mockResponse))
118
+
119
+ const pkg = {
120
+ packageName: 'packageName',
121
+ packageVersion: '1.0.0'
122
+ }
123
+
124
+ // the manifest() method should throw an error
125
+ // in this jest mock to simulate a problem:
126
+ pacote.manifest = jest.fn().mockRejectedValue(new Error('mocked manifest error'))
127
+
128
+ const testMarshall = new ProvenanceMarshall({
129
+ packageRepoUtils: {
130
+ getPackageInfo: (pkgInfo) => {
131
+ return new Promise((resolve) => {
132
+ resolve({
133
+ name: pkg.packageName,
134
+ version: pkg.packageVersion
135
+ })
136
+ })
137
+ },
138
+ parsePackageVersion: (pkgVersion) => {
139
+ return {
140
+ version: pkgVersion
141
+ }
142
+ }
143
+ }
144
+ })
145
+
146
+ // We assert that the validate method didn't throw an error,
147
+ // because the keys match the signature
148
+ await expect(testMarshall.validate(pkg)).rejects.toThrow('mocked manifest error')
149
+
150
+ // Assert that the fetch method is called with the correct URL
151
+ // eslint-disable-next-line no-undef
152
+ expect(fetch).toHaveBeenCalledWith('https://registry.npmjs.org/-/npm/v1/keys')
153
+ })
154
+
155
+ test('should throw a warning if attestations cant be found for the package', async () => {
156
+ // Mock the response from fetch
157
+ const mockResponse = {
158
+ json: jest.fn().mockResolvedValue({
159
+ keys: [
160
+ {
161
+ key: 'publicKey1'
162
+ },
163
+ {
164
+ key: 'publicKey2'
165
+ }
166
+ ]
167
+ })
168
+ }
169
+ fetch.mockImplementationOnce(() => Promise.resolve(mockResponse))
170
+
171
+ const pkg = {
172
+ packageName: 'packageName',
173
+ packageVersion: '1.0.0'
174
+ }
175
+
176
+ pacote.manifest = jest.fn().mockResolvedValue({
177
+ name: 'packageName',
178
+ version: '1.0.0'
179
+ })
180
+
181
+ const testMarshall = new ProvenanceMarshall({
182
+ packageRepoUtils: {
183
+ getPackageInfo: (pkgInfo) => {
184
+ return new Promise((resolve) => {
185
+ resolve({
186
+ name: pkg.packageName,
187
+ version: pkg.packageVersion
188
+ })
189
+ })
190
+ },
191
+ parsePackageVersion: (pkgVersion) => {
192
+ return {
193
+ version: pkgVersion
194
+ }
195
+ }
196
+ }
197
+ })
198
+
199
+ // We assert that the validate method didn't throw an error,
200
+ // because the keys match the signature
201
+ await expect(testMarshall.validate(pkg)).rejects.toThrow(
202
+ 'the package was published without any attestations. Proceed with care.'
203
+ )
204
+
205
+ // Assert that the fetch method is called with the correct URL
206
+ // eslint-disable-next-line no-undef
207
+ expect(fetch).toHaveBeenCalledWith('https://registry.npmjs.org/-/npm/v1/keys')
208
+ })
209
+ })
@@ -9,6 +9,10 @@ jest.mock('pacote', () => {
9
9
  }
10
10
  })
11
11
 
12
+ jest.mock('node-fetch')
13
+
14
+ const fetch = require('node-fetch')
15
+
12
16
  const SignaturesMarshall = require('../lib/marshalls/signatures.marshall')
13
17
  const pacote = require('pacote')
14
18
 
@@ -46,7 +50,7 @@ describe('Signature test suites', () => {
46
50
  ]
47
51
  })
48
52
  }
49
- global.fetch = jest.fn().mockResolvedValue(mockResponse)
53
+ fetch.mockImplementationOnce(() => Promise.resolve(mockResponse))
50
54
 
51
55
  const testMarshall = new SignaturesMarshall({
52
56
  packageRepoUtils: {
@@ -103,7 +107,7 @@ describe('Signature test suites', () => {
103
107
  ]
104
108
  })
105
109
  }
106
- global.fetch = jest.fn().mockResolvedValue(mockResponse)
110
+ fetch.mockImplementationOnce(() => Promise.resolve(mockResponse))
107
111
 
108
112
  // the manifest() method should throw an error
109
113
  // in this jest mock to simulate a problem:
@@ -1,7 +1,9 @@
1
1
  'use strict'
2
2
 
3
3
  const BaseMarshall = require('./baseMarshall')
4
+ const fetch = require('node-fetch')
4
5
  const pacote = require('pacote')
6
+ const Warning = require('../helpers/warning')
5
7
 
6
8
  const MARSHALL_NAME = 'provenance'
7
9
 
@@ -44,7 +46,15 @@ class Marshall extends BaseMarshall {
44
46
  })
45
47
  })
46
48
  .then((metadata) => {
47
- return metadata
49
+ if (!metadata || !metadata._attestations) {
50
+ throw new Warning(
51
+ 'the package was published without any attestations. Proceed with care.'
52
+ )
53
+ }
54
+
55
+ const attestations = metadata._attestations
56
+
57
+ return attestations
48
58
  })
49
59
  }
50
60
 
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const BaseMarshall = require('./baseMarshall')
4
+ const fetch = require('node-fetch')
4
5
  const pacote = require('pacote')
5
6
 
6
7
  const MARSHALL_NAME = 'signatures'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "npq",
3
- "version": "2.5.1",
3
+ "version": "2.5.3",
4
4
  "description": "marshall your npm/npm package installs with high quality and class 🎖",
5
5
  "bin": {
6
6
  "npq": "./bin/npq.js",