Skip to content

Commit f66d733

Browse files
Charles Lydingfilipesilva
Charles Lyding
authored andcommitted
feat(@angular/cli): support subresource integrity validation
1 parent fa35a32 commit f66d733

File tree

7 files changed

+38
-0
lines changed

7 files changed

+38
-0
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
"webpack-dev-middleware": "~1.12.0",
9898
"webpack-dev-server": "~2.7.1",
9999
"webpack-merge": "^4.1.0",
100+
"webpack-subresource-integrity": "^1.0.1",
100101
"zone.js": "^0.8.14"
101102
},
102103
"devDependencies": {

packages/@angular/cli/commands/build.ts

+7
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,13 @@ export const baseBuildCommandOptions: any = [
184184
// aliases: ['eac'], // We should not have shorthand aliases for experimental flags.
185185
description: '(Experimental) Use new Angular Compiler (Angular version 5 and greater only).',
186186
default: AngularCompilerPlugin.isSupported()
187+
},
188+
{
189+
name: 'subresource-integrity',
190+
type: Boolean,
191+
default: false,
192+
aliases: ['sri'],
193+
description: 'Enables the use of subresource integrity validation.'
187194
}
188195
];
189196

packages/@angular/cli/models/build-options.ts

+1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ export interface BuildOptions {
2626
buildOptimizer?: boolean;
2727
namedChunks?: boolean;
2828
experimentalAngularCompiler?: boolean;
29+
subresourceIntegrity?: boolean;
2930
}

packages/@angular/cli/models/webpack-configs/browser.ts

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as fs from 'fs';
22
import * as webpack from 'webpack';
33
import * as path from 'path';
44
const HtmlWebpackPlugin = require('html-webpack-plugin');
5+
const SubresourceIntegrityPlugin = require('webpack-subresource-integrity');
56

67
import { packageChunkSort } from '../../utilities/package-chunk-sort';
78
import { BaseHrefWebpackPlugin } from '../../lib/base-href-webpack';
@@ -60,7 +61,16 @@ export function getBrowserConfig(wco: WebpackConfigOptions) {
6061
}));
6162
}
6263

64+
if (buildOptions.subresourceIntegrity) {
65+
extraPlugins.push(new SubresourceIntegrityPlugin({
66+
hashFuncNames: ['sha384']
67+
}));
68+
}
69+
6370
return {
71+
output: {
72+
crossOriginLoading: buildOptions.subresourceIntegrity ? 'anonymous' : false
73+
},
6474
plugins: [
6575
new HtmlWebpackPlugin({
6676
template: path.resolve(appRoot, appConfig.index),

packages/@angular/cli/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"webpack-dev-middleware": "~1.12.0",
8282
"webpack-dev-server": "~2.7.1",
8383
"webpack-merge": "^4.1.0",
84+
"webpack-subresource-integrity": "^1.0.1",
8485
"zone.js": "^0.8.14"
8586
},
8687
"optionalDependencies": {

packages/@angular/cli/tasks/eject.ts

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const angularCliPlugins = require('../plugins/webpack');
2121

2222
const ExtractTextPlugin = require('extract-text-webpack-plugin');
2323
const HtmlWebpackPlugin = require('html-webpack-plugin');
24+
const SubresourceIntegrityPlugin = require('webpack-subresource-integrity');
2425
const SilentError = require('silent-error');
2526
const CircularDependencyPlugin = require('circular-dependency-plugin');
2627
const ConcatPlugin = require('webpack-concat-plugin');
@@ -242,6 +243,10 @@ class JsonWebpackSerializer {
242243
args = this._uglifyjsPlugin(plugin);
243244
this.variableImports['uglifyjs-webpack-plugin'] = 'UglifyJsPlugin';
244245
break;
246+
case SubresourceIntegrityPlugin:
247+
this.variableImports['webpack-subresource-integrity'] = 'SubresourceIntegrityPlugin';
248+
break;
249+
245250
default:
246251
if (plugin.constructor.name == 'AngularServiceWorkerPlugin') {
247252
this._addImport('@angular/service-worker/build/webpack', plugin.constructor.name);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { expectFileToMatch } from '../../utils/fs';
2+
import { ng } from '../../utils/process';
3+
import { expectToFail } from '../../utils/utils';
4+
5+
const integrityRe = /integrity="\w+-[A-Za-z0-9\/\+=]+"/;
6+
7+
export default async function() {
8+
return ng('build')
9+
.then(() => expectToFail(() =>
10+
expectFileToMatch('dist/index.html', integrityRe)))
11+
.then(() => ng('build', '--sri'))
12+
.then(() => expectFileToMatch('dist/index.html', integrityRe));
13+
}

0 commit comments

Comments
 (0)