diff options
author | Ed Tanous <ed.tanous@intel.com> | 2018-12-19 17:59:28 -0800 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2018-12-22 17:36:03 +0000 |
commit | 0f2f981e3218a57f89995aa6cb6b684b2ec0ba8f (patch) | |
tree | 7140663c2b9acfa7da750fb4d86fb9982bf2514a | |
parent | 7c2b7c124f620da1ff0f8a70fd32b93e97d28871 (diff) | |
download | phosphor-webui-0f2f981e3218a57f89995aa6cb6b684b2ec0ba8f.tar.gz phosphor-webui-0f2f981e3218a57f89995aa6cb6b684b2ec0ba8f.zip |
Enable strict content security policy
Webpack allows us to define a content security policy that utilizes
hashes to define what is, and isn't allowed to execute in the page
context. Because we're a single page application, this means that we
can effectively defend the whole page with a few extra lines of setup.
This does not utilitize _any_ of the unsafe-* calls that content
security policy has, which should meet security standards for all uses.
Tested By:
Launched GUI, observed no functional changes, and watched console for
CSP errors. Saw none.
Change-Id: I892df1f1b004384943be0ae6e51046054991fd45
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
-rw-r--r-- | app/index.html | 1 | ||||
-rw-r--r-- | package-lock.json | 83 | ||||
-rw-r--r-- | package.json | 15 | ||||
-rw-r--r-- | webpack.config.js | 34 |
4 files changed, 103 insertions, 30 deletions
diff --git a/app/index.html b/app/index.html index 62ddfc5..63ee778 100644 --- a/app/index.html +++ b/app/index.html @@ -2,6 +2,7 @@ <html ng-app="app" ng-csp lang="en"> <head> + <meta http-equiv="Content-Security-Policy" content="%%CSP_CONTENT%%"> <meta charset="UTF-8"> <title>OpenBMC</title> <meta name="viewport" content="width=device-width, initial-scale=1"> diff --git a/package-lock.json b/package-lock.json index 379caed..07d2a7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -713,6 +713,12 @@ "to-fast-properties": "2.0.0" } }, + "@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", + "dev": true + }, "@uirouter/core": { "version": "5.0.21", "resolved": "https://registry.npmjs.org/@uirouter/core/-/core-5.0.21.tgz", @@ -1947,6 +1953,20 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "cheerio": { + "version": "1.0.0-rc.2", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", + "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", + "dev": true, + "requires": { + "css-select": "1.2.0", + "dom-serializer": "0.1.0", + "entities": "1.1.1", + "htmlparser2": "3.10.0", + "lodash": "4.17.10", + "parse5": "3.0.3" + } + }, "chownr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", @@ -2503,6 +2523,24 @@ "randomfill": "1.0.4" } }, + "csp-html-webpack-plugin": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/csp-html-webpack-plugin/-/csp-html-webpack-plugin-2.5.0.tgz", + "integrity": "sha512-cL3fiTv1ebu5FnfmgJUZG6lSI/k0K+QDcza2rZyHw9xcWE4hGoD0cL3rAPvCAPa+OrFMrbj35RqkHXISWwm2Uw==", + "dev": true, + "requires": { + "cheerio": "1.0.0-rc.2", + "lodash": "4.17.11" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } + } + }, "css-loader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.0.tgz", @@ -2949,6 +2987,15 @@ "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", "dev": true }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, "domutils": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", @@ -4496,6 +4543,33 @@ } } }, + "htmlparser2": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz", + "integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.4.2", + "domutils": "1.5.1", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "3.1.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.0.tgz", + "integrity": "sha512-vpydAvIJvPODZNagCPuHG87O9JNPtvFEtjHHRVwNVsVVRBqemvPJkc2SYbxJsiZXawJdtZNmkmnsPuE3IgsG0A==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + } + } + }, "http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", @@ -6453,6 +6527,15 @@ "error-ex": "1.3.2" } }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "10.12.18" + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", diff --git a/package.json b/package.json index 2216e73..c4ed8e5 100644 --- a/package.json +++ b/package.json @@ -51,28 +51,29 @@ "babel-loader": "8.0.2", "compression-webpack-plugin": "2.0.0", "copy-webpack-plugin": "4.5.2", + "csp-html-webpack-plugin": "^2.5.0", "css-loader": "1.0.0", "eslint-plugin-angular": "3.3.0", "event-stream": "3.3.4", "file-loader": "2.0.0", + "filter-chunk-webpack-plugin": "^2.1.0", "html-loader": "^0.5.5", "html-minifier": "^3.5.20", + "html-webpack-inline-source-plugin": "0.0.10", "html-webpack-plugin": "^3.2.0", + "ignore-assets-webpack-plugin": "^2.0.1", + "mini-css-extract-plugin": "^0.4.2", "node-sass": "^4.9.3", "null-loader": "^0.1.1", "raw-loader": "^0.5.1", "rimraf": "^2.5.1", "sass-loader": "^7.1.0", "style-loader": "^0.23.0", + "svg-inline-loader": "^0.8.0", "uglifyjs-webpack-plugin": "^1.3.0", "webpack": "^4.17.2", - "webpack-dev-server": "^3.1.7", - "html-webpack-inline-source-plugin": "0.0.10", - "ignore-assets-webpack-plugin": "^2.0.1", - "filter-chunk-webpack-plugin": "^2.1.0", - "mini-css-extract-plugin": "^0.4.2", - "svg-inline-loader": "^0.8.0", - "webpack-cli": "^3.1.0" + "webpack-cli": "^3.1.0", + "webpack-dev-server": "^3.1.7" }, "license": "MIT", "engines": { diff --git a/webpack.config.js b/webpack.config.js index 1d66f12..91cbea8 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,12 +5,11 @@ var webpack = require('webpack'); var autoprefixer = require('autoprefixer'); var HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin'); +var CSPWebpackPlugin = require('csp-html-webpack-plugin'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var CopyWebpackPlugin = require('copy-webpack-plugin'); var CompressionPlugin = require('compression-webpack-plugin'); -var AssetsPlugin = require('assets-webpack-plugin'); var path = require('path'); -var UglifyJsPlugin = require('uglifyjs-webpack-plugin'); var FilterChunkWebpackPlugin = require('filter-chunk-webpack-plugin'); var MiniCssExtractPlugin = require('mini-css-extract-plugin'); @@ -75,7 +74,7 @@ module.exports = (env, options) => { use: 'babel-loader', exclude: /node_modules/ }, - {test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader']}, { + { // ASSET LOADER // Reference: https://github.com/webpack/file-loader // Copy png, jpg, jpeg, gif, svg, woff, woff2, ttf, eot files to @@ -95,19 +94,9 @@ module.exports = (env, options) => { test: /\.html$/, loader: 'html-loader' }, - { + {test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader']}, { test: /\.scss$/, - use: [ - { - loader: 'style-loader' // creates style nodes from JS strings - }, - { - loader: 'css-loader' // translates CSS into CommonJS - }, - { - loader: 'sass-loader' // compiles Sass to CSS - } - ] + use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] } ] }; @@ -117,19 +106,19 @@ module.exports = (env, options) => { template: './app/index.html', inject: 'body', favicon: './app/assets/images/favicon.ico', - inlineSource: '.(js|css)$', // embed all javascript and css inline minify: {removeComments: true, collapseWhitespace: true}, }), - new MiniCssExtractPlugin(), new HtmlWebpackInlineSourcePlugin(), + new CSPWebpackPlugin({ + 'base-uri': '\'self\'', + 'object-src': '\'none\'', + 'script-src': ['\'self\''], + 'style-src': ['\'self\''] + }), + new MiniCssExtractPlugin(), new FilterChunkWebpackPlugin({ - // The webpack inline source plugin will embed the css and javascript - // into our html, so we need to strip it out here so it doesn't take - // up space patterns: [ - '*.css', - '*.js', '*glyphicons-halflings-regular*.ttf', '*glyphicons-halflings-regular*.svg', '*glyphicons-halflings-regular*.eot', @@ -138,7 +127,6 @@ module.exports = (env, options) => { }) ]; - // Add build specific plugins if (isProd) { config.plugins.push(new CompressionPlugin({deleteOriginalAssets: true})); |