Skip to content

Commit

Permalink
Fix prototype pollution in mergeConfig.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeffrey Heer authored and jheer committed Mar 5, 2020
1 parent 99c37e0 commit 8f33a0b
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
8 changes: 6 additions & 2 deletions packages/vega-util/src/mergeConfig.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import isArray from './isArray';
import isObject from './isObject';

const isLegalKey = key => key !== '__proto__';

export function mergeConfig(...configs) {
return configs.reduce((out, source) => {
for (var key in source) {
Expand All @@ -14,7 +16,7 @@ export function mergeConfig(...configs) {
// for legend block, recurse for the layout entry only
// for style block, recurse for all properties
// otherwise, no recursion: objects overwrite, no merging
var r = key === 'legend' ? {'layout': 1}
var r = key === 'legend' ? {layout: 1}
: key === 'style' ? true
: null;
writeConfig(out, key, source[key], r);
Expand All @@ -25,13 +27,15 @@ export function mergeConfig(...configs) {
}

export function writeConfig(output, key, value, recurse) {
if (!isLegalKey(key)) return;

var k, o;
if (isObject(value) && !isArray(value)) {
o = isObject(output[key]) ? output[key] : (output[key] = {});
for (k in value) {
if (recurse && (recurse === true || recurse[k])) {
writeConfig(o, k, value[k]);
} else {
} else if (isLegalKey(k)) {
o[k] = value[k];
}
}
Expand Down
12 changes: 12 additions & 0 deletions packages/vega-util/test/mergeConfig-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,15 @@ tape('mergeConfig handles empty arguments', function(t) {
t.deepEqual(vega.mergeConfig(null, undefined, c), c);
t.end();
});

tape('mergeConfig must not allow prototype pollution', function(t) {
const config = {symbol: {shape: 'triangle-right'}},
payload = JSON.parse('{"__proto__": {"vulnerable": "Polluted"}}'),
merged = vega.mergeConfig(config, payload, {symbol: payload});

t.equal(merged.__proto__.vulnerable, undefined);
t.equal(merged.symbol.__proto__.vulnerable, undefined);
t.equal(Object.prototype.vulnerable, undefined);

t.end();
});

0 comments on commit 8f33a0b

Please sign in to comment.