mirror of https://github.com/grpc/grpc-node.git
Merge pull request #3 from d3v53c/huntr/proto-01
Prototype pollution fix - checking magic attributes - grpc-js
This commit is contained in:
commit
4cf11dc119
|
@ -93,6 +93,15 @@ export interface ServiceClientConstructor {
|
||||||
service: ServiceDefinition;
|
service: ServiceDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true, if given key is included in the blacklisted
|
||||||
|
* keys.
|
||||||
|
* @param key key for check, string.
|
||||||
|
*/
|
||||||
|
function isPrototypePolluted(key: string): Boolean {
|
||||||
|
return ['__proto__', 'prototype', 'constructor'].includes(key);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a constructor for a client with the given methods, as specified in
|
* Creates a constructor for a client with the given methods, as specified in
|
||||||
* the methods argument. The resulting class will have an instance method for
|
* the methods argument. The resulting class will have an instance method for
|
||||||
|
@ -122,7 +131,7 @@ export function makeClientConstructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(methods).forEach((name) => {
|
Object.keys(methods).forEach((name) => {
|
||||||
if (name === '__proto__') {
|
if (isPrototypePolluted(name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const attrs = methods[name];
|
const attrs = methods[name];
|
||||||
|
@ -155,7 +164,7 @@ export function makeClientConstructor(
|
||||||
ServiceClientImpl.prototype[name] = methodFunc;
|
ServiceClientImpl.prototype[name] = methodFunc;
|
||||||
// Associate all provided attributes with the method
|
// Associate all provided attributes with the method
|
||||||
Object.assign(ServiceClientImpl.prototype[name], attrs);
|
Object.assign(ServiceClientImpl.prototype[name], attrs);
|
||||||
if (attrs.originalName && attrs.originalName !== '__proto__') {
|
if (attrs.originalName && !isPrototypePolluted(attrs.originalName)) {
|
||||||
ServiceClientImpl.prototype[attrs.originalName] =
|
ServiceClientImpl.prototype[attrs.originalName] =
|
||||||
ServiceClientImpl.prototype[name];
|
ServiceClientImpl.prototype[name];
|
||||||
}
|
}
|
||||||
|
@ -204,7 +213,7 @@ export function loadPackageDefinition(
|
||||||
if (Object.prototype.hasOwnProperty.call(packageDef, serviceFqn)) {
|
if (Object.prototype.hasOwnProperty.call(packageDef, serviceFqn)) {
|
||||||
const service = packageDef[serviceFqn];
|
const service = packageDef[serviceFqn];
|
||||||
const nameComponents = serviceFqn.split('.');
|
const nameComponents = serviceFqn.split('.');
|
||||||
if (nameComponents.some(comp => comp === '__proto__')) {
|
if (nameComponents.some((comp: string) => isPrototypePolluted(comp))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const serviceName = nameComponents[nameComponents.length - 1];
|
const serviceName = nameComponents[nameComponents.length - 1];
|
||||||
|
|
|
@ -24,4 +24,8 @@ describe('loadPackageDefinition', () => {
|
||||||
loadPackageDefinition({'__proto__.polluted': true} as any);
|
loadPackageDefinition({'__proto__.polluted': true} as any);
|
||||||
assert.notStrictEqual(({} as any).polluted, true);
|
assert.notStrictEqual(({} as any).polluted, true);
|
||||||
});
|
});
|
||||||
|
it('Should not allow prototype pollution #2', () => {
|
||||||
|
loadPackageDefinition({'constructor.prototype.polluted': true} as any);
|
||||||
|
assert.notStrictEqual(({} as any).polluted, true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue