grpc: Prevent prototype pollution in loadPackageDefinition

This commit is contained in:
Michael Lumish 2020-10-20 11:18:19 -07:00
parent 96803d4e6d
commit 01cbcab070
3 changed files with 34 additions and 1 deletions

View File

@ -161,6 +161,9 @@ exports.loadPackageDefinition = function loadPackageDefintion(packageDef) {
for (const serviceFqn in packageDef) { for (const serviceFqn in packageDef) {
const service = packageDef[serviceFqn]; const service = packageDef[serviceFqn];
const nameComponents = serviceFqn.split('.'); const nameComponents = serviceFqn.split('.');
if (nameComponents.some(comp => comp === '__proto__')) {
continue;
}
const serviceName = nameComponents[nameComponents.length-1]; const serviceName = nameComponents[nameComponents.length-1];
let current = result; let current = result;
for (const packageName of nameComponents.slice(0, -1)) { for (const packageName of nameComponents.slice(0, -1)) {

View File

@ -992,6 +992,9 @@ exports.makeClientConstructor = function(methods, serviceName,
Object.keys(methods).forEach(name => { Object.keys(methods).forEach(name => {
const attrs = methods[name]; const attrs = methods[name];
if (name === '__proto__') {
return;
}
if (name.indexOf('$') === 0) { if (name.indexOf('$') === 0) {
throw new Error('Method names cannot start with $'); throw new Error('Method names cannot start with $');
} }
@ -1011,7 +1014,7 @@ exports.makeClientConstructor = function(methods, serviceName,
ServiceClient.prototype.$method_names[attrs.path] = name; ServiceClient.prototype.$method_names[attrs.path] = name;
// Associate all provided attributes with the method // Associate all provided attributes with the method
Object.assign(ServiceClient.prototype[name], attrs); Object.assign(ServiceClient.prototype[name], attrs);
if (attrs.originalName) { if (attrs.originalName && attrs.originalName !== '__proto__') {
ServiceClient.prototype[attrs.originalName] = ServiceClient.prototype[attrs.originalName] =
ServiceClient.prototype[name]; ServiceClient.prototype[name];
} }

View File

@ -0,0 +1,27 @@
/*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import * as assert from 'assert';
const grpc = require('../');
describe('loadPackageDefinition', () => {
it('Should not allow prototype pollution', () => {
grpc.loadPackageDefinition({'__proto__.polluted': true});
assert.notStrictEqual({}.polluted, true);
});
});