@@ -4,6 +4,7 @@ const localeCompare = require('@isaacs/string-locale-compare')('en')
44const npa = require ( 'npm-package-arg' )
55const pacote = require ( 'pacote' )
66const pMap = require ( 'p-map' )
7+ const { sigstore } = require ( 'sigstore' )
78
89const ArboristWorkspaceCmd = require ( '../arborist-cmd.js' )
910const auditError = require ( '../utils/audit-error.js' )
@@ -37,7 +38,12 @@ class VerifySignatures {
3738 throw new Error ( 'found no installed dependencies to audit' )
3839 }
3940
40- await Promise . all ( [ ...registries ] . map ( registry => this . setKeys ( { registry } ) ) )
41+ const tuf = await sigstore . tuf . client ( {
42+ tufCachePath : this . opts . tufCache ,
43+ retry : this . opts . retry ,
44+ timeout : this . opts . timeout ,
45+ } )
46+ await Promise . all ( [ ...registries ] . map ( registry => this . setKeys ( { registry, tuf } ) ) )
4147
4248 const progress = log . newItem ( 'verifying registry signatures' , edges . size )
4349 const mapper = async ( edge ) => {
@@ -187,20 +193,42 @@ class VerifySignatures {
187193 return { edges, registries }
188194 }
189195
190- async setKeys ( { registry } ) {
191- const keys = await fetch . json ( '/-/npm/v1/keys' , {
192- ...this . npm . flatOptions ,
193- registry,
194- } ) . then ( ( { keys : ks } ) => ks . map ( ( key ) => ( {
195- ...key ,
196- pemkey : `-----BEGIN PUBLIC KEY-----\n${ key . key } \n-----END PUBLIC KEY-----` ,
197- } ) ) ) . catch ( err => {
198- if ( err . code === 'E404' || err . code === 'E400' ) {
199- return null
200- } else {
201- throw err
202- }
203- } )
196+ async setKeys ( { registry, tuf } ) {
197+ const { host, pathname } = new URL ( registry )
198+ // Strip any trailing slashes from pathname
199+ const regKey = `${ host } ${ pathname . replace ( / \/ $ / , '' ) } /keys.json`
200+ let keys = await tuf . getTarget ( regKey )
201+ . then ( ( target ) => JSON . parse ( target ) )
202+ . then ( ( { keys : ks } ) => ks . map ( ( key ) => ( {
203+ ...key ,
204+ keyid : key . keyId ,
205+ pemkey : `-----BEGIN PUBLIC KEY-----\n${ key . publicKey . rawBytes } \n-----END PUBLIC KEY-----` ,
206+ expires : key . publicKey . validFor . end || null ,
207+ } ) ) ) . catch ( err => {
208+ if ( err . code === 'TUF_FIND_TARGET_ERROR' ) {
209+ return null
210+ } else {
211+ throw err
212+ }
213+ } )
214+
215+ // If keys not found in Sigstore TUF repo, fallback to registry keys API
216+ if ( ! keys ) {
217+ keys = await fetch . json ( '/-/npm/v1/keys' , {
218+ ...this . npm . flatOptions ,
219+ registry,
220+ } ) . then ( ( { keys : ks } ) => ks . map ( ( key ) => ( {
221+ ...key ,
222+ pemkey : `-----BEGIN PUBLIC KEY-----\n${ key . key } \n-----END PUBLIC KEY-----` ,
223+ } ) ) ) . catch ( err => {
224+ if ( err . code === 'E404' || err . code === 'E400' ) {
225+ return null
226+ } else {
227+ throw err
228+ }
229+ } )
230+ }
231+
204232 if ( keys ) {
205233 this . keys . set ( registry , keys )
206234 }
0 commit comments