11const fs = require ( 'fs' ) ;
2+ const fsExtra = require ( 'fs-extra' ) ;
23const os = require ( 'os' ) ;
34const path = require ( 'path' ) ;
45const axios = require ( 'axios' ) ;
@@ -14,6 +15,7 @@ const getPort = require('get-port');
1415const prettyMilliseconds = require ( 'pretty-ms' ) ;
1516const moment = require ( 'moment' ) ;
1617const rc = require ( 'rc' ) ;
18+ const ssri = require ( 'ssri' ) ;
1719const util = require ( 'util' ) ;
1820const toLower = require ( 'lodash/toLower' ) ;
1921
@@ -245,27 +247,62 @@ function getPackageConfig(filePath) {
245247 return packageJSON ;
246248}
247249
250+ const verifyNpmPackageIntegrity = ( content , packageName ) => {
251+ const { code, stdout : expectedIntegrity , stderr } = shell . exec (
252+ `npm view ${ packageName } dist.integrity` ,
253+ {
254+ silent : true ,
255+ }
256+ ) ;
257+
258+ if ( code !== 0 ) {
259+ throw new Error ( stderr ) ;
260+ }
261+
262+ if ( ssri . checkData ( content , expectedIntegrity ) === false ) {
263+ printInfo ( 'expected integrity' , expectedIntegrity ) ;
264+ printInfo ( 'actual integrity' , ssri . fromData ( content ) ) ;
265+ throw new Error ( `${ packageName } verify integrity failed` ) ;
266+ }
267+
268+ return true ;
269+ } ;
270+
248271const downloadPackageFromNPM = async ( name , dest , registry = '' ) => {
249- fs . mkdirSync ( dest , { recursive : true } ) ;
272+ printInfo ( 'Downloading package...' ) ;
250273 debug ( 'starter directory:' , dest ) ;
251274
252- printInfo ( 'Downloading package...' ) ;
253275 let packCommand = `npm pack ${ name } --color` ;
254- if ( name ) {
276+ if ( registry ) {
255277 packCommand = `${ packCommand } --registry=${ registry } ` ;
256278 }
257279
280+ const tmpDir = os . tmpdir ( ) ;
258281 const { code, stdout, stderr } = shell . exec ( packCommand , {
259282 silent : true ,
260- cwd : dest ,
283+ cwd : os . tmpdir ( ) ,
261284 } ) ;
262285
263286 if ( code !== 0 ) {
264287 throw new Error ( stderr ) ;
265288 }
266289
267290 const packageName = stdout . trim ( ) ;
268- await tar . x ( { file : path . join ( dest , packageName ) , C : dest , strip : 1 } ) ;
291+ const tarballPath = path . join ( tmpDir , packageName ) ;
292+ if ( ! fs . existsSync ( tarballPath ) ) {
293+ throw new Error ( `download ${ packageName } failed` ) ;
294+ }
295+
296+ verifyNpmPackageIntegrity ( fs . readFileSync ( tarballPath ) , name ) ;
297+
298+ fs . mkdirSync ( dest , { recursive : true } ) ;
299+ await tar . x ( { file : tarballPath , C : dest , strip : 1 } ) ;
300+
301+ try {
302+ fsExtra . removeSync ( tarballPath ) ;
303+ } catch ( error ) {
304+ printWarning ( 'remove temp tarball file failed:' , tarballPath ) ;
305+ }
269306
270307 return dest ;
271308} ;
0 commit comments