diff --git a/packages/@angular/cli/models/webpack-configs/common.ts b/packages/@angular/cli/models/webpack-configs/common.ts index 614c9e16bc0e..732427a97deb 100644 --- a/packages/@angular/cli/models/webpack-configs/common.ts +++ b/packages/@angular/cli/models/webpack-configs/common.ts @@ -12,6 +12,7 @@ import { readTsconfig } from '../../utilities/read-tsconfig'; const ConcatPlugin = require('webpack-concat-plugin'); const ProgressPlugin = require('webpack/lib/ProgressPlugin'); const CircularDependencyPlugin = require('circular-dependency-plugin'); +const SilentError = require('silent-error'); /** @@ -96,6 +97,13 @@ export function getCommonConfig(wco: WebpackConfigOptions) { asset.output = asset.output || ''; asset.glob = asset.glob || ''; + // Prevent asset configurations from writing outside of the output path + const fullOutputPath = path.resolve(buildOptions.outputPath, asset.output); + if (!fullOutputPath.startsWith(path.resolve(buildOptions.outputPath))) { + const message = 'An asset cannot be written to a location outside of the output path.'; + throw new SilentError(message); + } + // Ensure trailing slash. if (isDirectory(path.resolve(asset.input))) { asset.input += '/'; diff --git a/tests/e2e/tests/build/assets.ts b/tests/e2e/tests/build/assets.ts index ce15e48a81c0..20f32e1dbf3f 100644 --- a/tests/e2e/tests/build/assets.ts +++ b/tests/e2e/tests/build/assets.ts @@ -26,6 +26,14 @@ export default function () { './src/output-asset.txt': 'output-asset.txt', './node_modules/some-package/node_modules-asset.txt': 'node_modules-asset.txt', })) + // Add invalid asset config in .angular-cli.json. + .then(() => updateJsonFile('.angular-cli.json', configJson => { + const app = configJson['apps'][0]; + app['assets'] = [ + { 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../package-folder' } + ]; + })) + .then(() => expectToFail(() => ng('build'))) // Add asset config in .angular-cli.json. .then(() => updateJsonFile('.angular-cli.json', configJson => { const app = configJson['apps'][0];