Skip to content

Commit cf0192f

Browse files
committed
Automatically hashing split filenames on production
This is to not expose other entry names - e.g. vendor~super_secret_admin_area~other_entry.js
1 parent 1acc67a commit cf0192f

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

lib/config-generator.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const tmp = require('tmp');
4545
const fs = require('fs');
4646
const path = require('path');
4747
const stringEscaper = require('./utils/string-escaper');
48+
const crypto = require('crypto');
4849

4950
class ConfigGenerator {
5051
/**
@@ -365,6 +366,25 @@ class ConfigGenerator {
365366
let splitChunks = {
366367
chunks: this.webpackConfig.shouldSplitEntryChunks ? 'all' : 'async'
367368
};
369+
370+
// hash the split filenames in production to protect exposing entry names
371+
if (this.webpackConfig.shouldSplitEntryChunks && this.webpackConfig.isProduction()) {
372+
// taken from SplitChunksPlugin
373+
const hashFilename = name => {
374+
return crypto
375+
.createHash('md4')
376+
.update(name)
377+
.digest('hex')
378+
.slice(0, 8);
379+
};
380+
381+
splitChunks.name = function(module, chunks, cacheGroup) {
382+
const names = chunks.map(c => c.name);
383+
384+
return cacheGroup + '~' + hashFilename(names.join('~'));
385+
};
386+
}
387+
368388
if (this.webpackConfig.sharedCommonsEntryName) {
369389
const cacheGroups = {};
370390
cacheGroups[this.webpackConfig.sharedCommonsEntryName] = {

test/config-generator.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,4 +824,30 @@ describe('The config-generator function', () => {
824824
});
825825
});
826826
});
827+
828+
describe('Test shouldSplitEntryChunks', () => {
829+
it('Not production', () => {
830+
const config = createConfig();
831+
config.outputPath = '/tmp/public/build';
832+
config.setPublicPath('/build/');
833+
config.splitEntryChunks();
834+
835+
const actualConfig = configGenerator(config);
836+
expect(actualConfig.optimization.splitChunks.chunks).to.equal('all');
837+
expect(actualConfig.optimization.splitChunks.name).to.be.undefined;
838+
});
839+
840+
it('Yes production', () => {
841+
const runtimeConfig = new RuntimeConfig();
842+
runtimeConfig.environment = 'production';
843+
const config = createConfig(runtimeConfig);
844+
config.outputPath = '/tmp/public/build';
845+
config.setPublicPath('/build/');
846+
config.splitEntryChunks();
847+
848+
const actualConfig = configGenerator(config);
849+
expect(actualConfig.optimization.splitChunks.chunks).to.equal('all');
850+
expect(actualConfig.optimization.splitChunks.name).to.be.a('function');
851+
});
852+
});
827853
});

0 commit comments

Comments
 (0)