66 * found in the LICENSE file at https://angular.io/license
77 */
88import { execSync } from 'child_process' ;
9+ import * as fs from 'fs' ;
910import * as path from 'path' ;
1011import * as semver from 'semver' ;
1112import { Arguments , Option } from '../models/interface' ;
@@ -22,10 +23,7 @@ import { Schema as UpdateCommandSchema } from './update';
2223
2324const npa = require ( 'npm-package-arg' ) ;
2425
25- const oldConfigFileNames = [
26- '.angular-cli.json' ,
27- 'angular-cli.json' ,
28- ] ;
26+ const oldConfigFileNames = [ '.angular-cli.json' , 'angular-cli.json' ] ;
2927
3028export class UpdateCommand extends SchematicCommand < UpdateCommandSchema > {
3129 public readonly allowMissingWorkspace = true ;
@@ -184,12 +182,45 @@ export class UpdateCommand extends SchematicCommand<UpdateCommandSchema> {
184182 } else if ( typeof migrations !== 'string' ) {
185183 this . logger . error ( 'Package contains a malformed migrations field.' ) ;
186184
185+ return 1 ;
186+ } else if ( path . posix . isAbsolute ( migrations ) || path . win32 . isAbsolute ( migrations ) ) {
187+ this . logger . error (
188+ 'Package contains an invalid migrations field. Absolute paths are not permitted.' ,
189+ ) ;
190+
187191 return 1 ;
188192 }
189193
190- // if not non-relative, add package name
191- if ( migrations . startsWith ( '.' ) || migrations . startsWith ( '/' ) ) {
192- migrations = path . join ( packageName , migrations ) ;
194+ // Normalize slashes
195+ migrations = migrations . replace ( / \\ / g, '/' ) ;
196+
197+ if ( migrations . startsWith ( '../' ) ) {
198+ this . logger . error (
199+ 'Package contains an invalid migrations field. ' +
200+ 'Paths outside the package root are not permitted.' ,
201+ ) ;
202+
203+ return 1 ;
204+ }
205+
206+ // Check if it is a package-local location
207+ const localMigrations = path . join ( packageNode . path , migrations ) ;
208+ if ( fs . existsSync ( localMigrations ) ) {
209+ migrations = localMigrations ;
210+ } else {
211+ // Try to resolve from package location.
212+ // This avoids issues with package hoisting.
213+ try {
214+ migrations = require . resolve ( migrations , { paths : [ packageNode . path ] } ) ;
215+ } catch ( e ) {
216+ if ( e . code === 'MODULE_NOT_FOUND' ) {
217+ this . logger . error ( 'Migrations for package were not found.' ) ;
218+ } else {
219+ this . logger . error ( `Unable to resolve migrations for package. [${ e . message } ]` ) ;
220+ }
221+
222+ return 1 ;
223+ }
193224 }
194225
195226 return this . runSchematic ( {
@@ -219,9 +250,11 @@ export class UpdateCommand extends SchematicCommand<UpdateCommandSchema> {
219250 }
220251
221252 // If a specific version is requested and matches the installed version, skip.
222- if ( pkg . type === 'version' &&
223- typeof node === 'object' &&
224- node . package . version === pkg . fetchSpec ) {
253+ if (
254+ pkg . type === 'version' &&
255+ typeof node === 'object' &&
256+ node . package . version === pkg . fetchSpec
257+ ) {
225258 this . logger . info ( `Package '${ pkg . name } ' is already at '${ pkg . fetchSpec } '.` ) ;
226259 continue ;
227260 }
0 commit comments