Webpack 4 使用 unsafe-eval 构建 bricks CSP
Webpack 4 build bricks CSP with unsafe-eval
当我尝试执行我的 TypeScript + React Webpack 4 应用程序时,代码没有执行并出现错误:
未捕获的 EvalError:拒绝将字符串评估为 JavaScript,因为 'unsafe-eval' 不是以下内容安全策略指令中允许的脚本源:“script-src 'self'
但是,在生成的包中,我在第 1 行找到以下段落:
/* [...] */ get(e,t,n)}},_=Function("return this")(),C=new Map([[Map,T],[Set,T],[ /* [...] */
这当然是及时执行,导致上面的错误。
据我所知,某些东西似乎需要引用全局对象(又名 window
),并尝试通过调用 Function("return this")()
来获取它。
事实上,如果我更改生成的 app.<hash>.js
并将 ,_=Function("return this")()
替换为简单的 ,_=window
一切正常,并且没有任何 CSP 投诉。
package.json
{
"name": "web",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --port 1234 --hot --inline --mode=development",
"dev-twitch": "webpack-dev-server --port 1235 --hot --inline --mode=development",
"build": "webpack -p",
"build-dev": "webpack -d"
},
"author": "",
"license": "UNLICENSED",
"dependencies": {
"@types/node": "^10.12.12",
"@types/react": "^16.7.20",
"@types/react-dom": "^16.0.11",
"@types/react-transition-group": "^2.0.15",
"autobind-decorator": "^2.3.1",
"clean-webpack-plugin": "^1.0.1",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^1.0.1",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.5.0",
"node-sass": "^4.11.0",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-easy-state": "^6.0.6",
"react-transition-group": "^2.5.3",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"ts-loader": "^5.3.3",
"typescript": "^3.3.1",
"webpack": "^4.29.1",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.10",
"zip-webpack-plugin": "^3.0.0"
},
"devDependencies": {}
}
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ZipPlugin = require('zip-webpack-plugin');
const htmlPlugins = [
new HtmlWebpackPlugin({
template: './src/index.html',
inject: 'body',
filename: 'index.html',
chunks: ['app'],
}),
];
let appIndex = './src/ts/_entry.tsx';
let outDir = 'dist';
module.exports = (env) => {
const devMode = process.argv.find(v => v.includes('webpack-dev-server'));
const styleLoader = devMode ? 'style-loader' : MiniCssExtractPlugin.loader;
const cssPlugins = [];
if (!devMode) {
cssPlugins.push(
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css',
})
);
}
return ({
entry: {
app: appIndex,
},
output: {
path: path.resolve(__dirname, outDir),
filename: '[name].[hash].js'
}, resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: ['.ts', '.tsx', '.js'],
alias: {
src: path.resolve(__dirname, 'src/')
}
},
devtool: 'hidden-source-map',
node: {
global: false,
},
plugins: [
...htmlPlugins,
...cssPlugins,
new CleanWebpackPlugin('./' + outDir),
new CopyWebpackPlugin([{
from: './src/assets',
to: './assets/'
}]),
new ZipPlugin({
filename: 'dist-twitch.zip',
path: __dirname,
}),
],
module: {
rules: [
{ test: /\.tsx?$/, use: 'ts-loader' },
{ test: /\.(svg|woff|ttf|eot|woff2|otf)$/, use: 'file-loader' },
{ test: /\.(png|jpg|jpeg)$/, use: 'file-loader' },
{ test: /\.scss$/, use: [styleLoader, 'css-loader','sass-loader'] },
{ test: /\.css$/, use: [styleLoader, 'css-loader'] },
]
},
devServer: {
clientLogLevel: 'error',
overlay: true,
proxy: {
'/join': 'http://localhost',
},
}
});
}
如何修改构建,这样我就不必手动修改结果了?我怎样才能最好地找出导致错误代码的模块?
事实证明,罪魁祸首是 react-easy-state
要求的 @nx-js/observer-util
。
我写了一个 pull request 应该可以解决这个问题。
我通过在我的配置中添加 'devtool: "source-map"' 解决了这个问题。请看下面。
const clientConfig = {
mode: 'production',
target: 'web',
devtool: "source-map",
entry: {
...
},
module: {
rules: [
...
],
},
output: {
...
},
resolve: {
...
}
}
module.exports = [clientConfig]
我发现了这个解决方案 here。
当我尝试执行我的 TypeScript + React Webpack 4 应用程序时,代码没有执行并出现错误:
未捕获的 EvalError:拒绝将字符串评估为 JavaScript,因为 'unsafe-eval' 不是以下内容安全策略指令中允许的脚本源:“script-src 'self'
但是,在生成的包中,我在第 1 行找到以下段落:
/* [...] */ get(e,t,n)}},_=Function("return this")(),C=new Map([[Map,T],[Set,T],[ /* [...] */
这当然是及时执行,导致上面的错误。
据我所知,某些东西似乎需要引用全局对象(又名 window
),并尝试通过调用 Function("return this")()
来获取它。
事实上,如果我更改生成的 app.<hash>.js
并将 ,_=Function("return this")()
替换为简单的 ,_=window
一切正常,并且没有任何 CSP 投诉。
package.json
{
"name": "web",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --port 1234 --hot --inline --mode=development",
"dev-twitch": "webpack-dev-server --port 1235 --hot --inline --mode=development",
"build": "webpack -p",
"build-dev": "webpack -d"
},
"author": "",
"license": "UNLICENSED",
"dependencies": {
"@types/node": "^10.12.12",
"@types/react": "^16.7.20",
"@types/react-dom": "^16.0.11",
"@types/react-transition-group": "^2.0.15",
"autobind-decorator": "^2.3.1",
"clean-webpack-plugin": "^1.0.1",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^1.0.1",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.5.0",
"node-sass": "^4.11.0",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-easy-state": "^6.0.6",
"react-transition-group": "^2.5.3",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"ts-loader": "^5.3.3",
"typescript": "^3.3.1",
"webpack": "^4.29.1",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.10",
"zip-webpack-plugin": "^3.0.0"
},
"devDependencies": {}
}
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ZipPlugin = require('zip-webpack-plugin');
const htmlPlugins = [
new HtmlWebpackPlugin({
template: './src/index.html',
inject: 'body',
filename: 'index.html',
chunks: ['app'],
}),
];
let appIndex = './src/ts/_entry.tsx';
let outDir = 'dist';
module.exports = (env) => {
const devMode = process.argv.find(v => v.includes('webpack-dev-server'));
const styleLoader = devMode ? 'style-loader' : MiniCssExtractPlugin.loader;
const cssPlugins = [];
if (!devMode) {
cssPlugins.push(
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
chunkFilename: '[id].[hash].css',
})
);
}
return ({
entry: {
app: appIndex,
},
output: {
path: path.resolve(__dirname, outDir),
filename: '[name].[hash].js'
}, resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: ['.ts', '.tsx', '.js'],
alias: {
src: path.resolve(__dirname, 'src/')
}
},
devtool: 'hidden-source-map',
node: {
global: false,
},
plugins: [
...htmlPlugins,
...cssPlugins,
new CleanWebpackPlugin('./' + outDir),
new CopyWebpackPlugin([{
from: './src/assets',
to: './assets/'
}]),
new ZipPlugin({
filename: 'dist-twitch.zip',
path: __dirname,
}),
],
module: {
rules: [
{ test: /\.tsx?$/, use: 'ts-loader' },
{ test: /\.(svg|woff|ttf|eot|woff2|otf)$/, use: 'file-loader' },
{ test: /\.(png|jpg|jpeg)$/, use: 'file-loader' },
{ test: /\.scss$/, use: [styleLoader, 'css-loader','sass-loader'] },
{ test: /\.css$/, use: [styleLoader, 'css-loader'] },
]
},
devServer: {
clientLogLevel: 'error',
overlay: true,
proxy: {
'/join': 'http://localhost',
},
}
});
}
如何修改构建,这样我就不必手动修改结果了?我怎样才能最好地找出导致错误代码的模块?
事实证明,罪魁祸首是 react-easy-state
要求的 @nx-js/observer-util
。
我写了一个 pull request 应该可以解决这个问题。
我通过在我的配置中添加 'devtool: "source-map"' 解决了这个问题。请看下面。
const clientConfig = {
mode: 'production',
target: 'web',
devtool: "source-map",
entry: {
...
},
module: {
rules: [
...
],
},
output: {
...
},
resolve: {
...
}
}
module.exports = [clientConfig]
我发现了这个解决方案 here。