Skip to content

Commit

Permalink
fixup! fix(merge): Avoid protototype pollution when parsing properties
Browse files Browse the repository at this point in the history
Signed-off-by: Paul Maréchal <[email protected]>
  • Loading branch information
paul-marechal committed Oct 29, 2020
1 parent f0171c2 commit 525f4d9
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 8 deletions.
5 changes: 2 additions & 3 deletions packages/plugin-ext/src/plugin/preference-registry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ describe('PreferenceRegistryExtImpl:', () => {
getProxy,
set,
dispose

} as RPCProtocol;
const mockWorkspace: WorkspaceExtImpl = {} as WorkspaceExtImpl;

Expand Down Expand Up @@ -67,7 +66,7 @@ describe('PreferenceRegistryExtImpl:', () => {
};
const result: { [key: string]: any } = (preferenceRegistryExtImpl as any).parseConfigurationData(value);
expect(result.my).to.be.an('object');
expect(result.__proto__).to.be.equal(Object.prototype);
expect(result.__proto__).to.be.an('undefined');
expect(result.my.key1.foo).to.equal('value1');
const prototypeObject = Object.prototype as any;
expect(prototypeObject.injectedParsedPrototype).to.be.an('undefined');
Expand All @@ -83,7 +82,7 @@ describe('PreferenceRegistryExtImpl:', () => {
};
const result: { [key: string]: any } = (preferenceRegistryExtImpl as any).parseConfigurationData(value);
expect(result.my).to.be.an('object');
expect(result.__proto__).to.be.equal(Object.prototype);
expect(result.__proto__).to.be.an('undefined');
expect(result.my.key1.foo).to.equal('value1');
const prototypeObject = Object.prototype as any;
expect(prototypeObject.injectedParsedConstructorPrototype).to.be.an('undefined');
Expand Down
11 changes: 7 additions & 4 deletions packages/plugin-ext/src/plugin/preference-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { Configuration, ConfigurationModel } from './preferences/configuration';
import { WorkspaceExtImpl } from './workspace';
import cloneDeep = require('lodash.clonedeep');

const prototypePropertyRe = /\b__proto__\b|\bconstructor.prototype\b/;
const injectionRe = /\b__proto__\b|\bconstructor\.prototype\b/;

enum ConfigurationTarget {
Global = 1,
Expand Down Expand Up @@ -240,7 +240,10 @@ export class PreferenceRegistryExtImpl implements PreferenceRegistryExt {
private readonly OVERRIDE_PROPERTY_PATTERN = new RegExp(this.OVERRIDE_PROPERTY);

private parseConfigurationData(data: { [key: string]: any }): { [key: string]: any } {
return Object.keys(data).filter(key => !prototypePropertyRe.test(key)).reduce((result: any, key: string) => {
return Object.keys(data).reduce((result: any, key: string) => {
if (injectionRe.test(key)) {
return result;
}
const parts = key.split('.');
let branch = result;

Expand All @@ -250,7 +253,7 @@ export class PreferenceRegistryExtImpl implements PreferenceRegistryExt {
continue;
}
if (!branch[parts[i]]) {
branch[parts[i]] = {};
branch[parts[i]] = Object.create(null);
}
branch = branch[parts[i]];

Expand All @@ -265,7 +268,7 @@ export class PreferenceRegistryExtImpl implements PreferenceRegistryExt {
}
}
return result;
}, {});
}, Object.create(null));
}

private toConfigurationChangeEvent(eventData: PreferenceChangeExt[]): theia.ConfigurationChangeEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class Configuration {
export class ConfigurationModel {

constructor(
private contents: any = {},
private contents: any = Object.create(null),
private keys: string[] = [],
) { }

Expand Down

0 comments on commit 525f4d9

Please sign in to comment.