Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

From my understanding of Content Security Policy, the nonce has to change on every request. That means (I think) it must be generated at run-time on the client, not at build-time in the Webpack config. I've tested the webpack_nonce functionality in my app and it works great.

Unfortunately, I'm not sure how to get that value, generated at run-time on the client, to the actual CSP policy, which is either set as a meta-tag in the index.html file (or some equivalent) or on the server itself.

I suppose you could set the CSP meta-tag dynamically on the client, but that seems like a security risk. I've experimented with the csp-webpack-plugin, which calculates hashes of files at build-time and then adds them to the index.html. This process makes sense to me, it just didn't support our use case.

I just feel like I'm missing something with using webpack_nonce.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
1.1k views
Welcome To Ask or Share your Answers For Others

1 Answer

We were able to get a dynamic nonce by having webpack build our index page (e.g via HtmlWebpackPlugin) as a template then serving it dynamically. This way, you can set __webpack_nonce__ to an interpolation expression like <%=nonce%> and the server view engine can sub in your dynamic nonce at page-load time. For example, if you're using express:

Webpack config:

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: __dirname + '/dist/index.ejs',
    })
  ]
}

Webpack entry point (index.js):

__webpack_nonce__ = '<%=nonce%>';

Express app:

// Generate dynamic nonce on each request cycle
const uuid = require('node-uuid');
app.use((req, res, next) => {
  res.locals.nonce = uuid.v4();
  next();
});

app.set('view engine', 'ejs');
app.route('/').get((req, res, next) => {
  res.render('path/to/index.ejs', { nonce: res.locals.nonce });
});

The injected <script> tags will have the literal attribute nonce=<%=nonce%> appended, which the server will then interpolate when serving your page.

Note that if you use a custom template with HtmlWebpackPlugin, you might want to set a different interpolation delimiter for ejs otherwise Webpack will interpolate the nonce expression at build time instead of runtime.

Express app:

const ejs = require('ejs);
ejs.delimiter = '?'; // Means instead use __webpack_nonce__ = '<?=nonce?>'

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...