diff --git a/packages/grpc-native-core/index.js b/packages/grpc-native-core/index.js index 9534c7d4f..e9053e8a0 100644 --- a/packages/grpc-native-core/index.js +++ b/packages/grpc-native-core/index.js @@ -161,6 +161,9 @@ exports.loadPackageDefinition = function loadPackageDefintion(packageDef) { for (const serviceFqn in packageDef) { const service = packageDef[serviceFqn]; const nameComponents = serviceFqn.split('.'); + if (nameComponents.some(comp => comp === '__proto__')) { + continue; + } const serviceName = nameComponents[nameComponents.length-1]; let current = result; for (const packageName of nameComponents.slice(0, -1)) { diff --git a/packages/grpc-native-core/src/client.js b/packages/grpc-native-core/src/client.js index faba6decb..7ca1aece5 100644 --- a/packages/grpc-native-core/src/client.js +++ b/packages/grpc-native-core/src/client.js @@ -992,6 +992,9 @@ exports.makeClientConstructor = function(methods, serviceName, Object.keys(methods).forEach(name => { const attrs = methods[name]; + if (name === '__proto__') { + return; + } if (name.indexOf('$') === 0) { throw new Error('Method names cannot start with $'); } @@ -1011,7 +1014,7 @@ exports.makeClientConstructor = function(methods, serviceName, ServiceClient.prototype.$method_names[attrs.path] = name; // Associate all provided attributes with the method Object.assign(ServiceClient.prototype[name], attrs); - if (attrs.originalName) { + if (attrs.originalName && attrs.originalName !== '__proto__') { ServiceClient.prototype[attrs.originalName] = ServiceClient.prototype[name]; } diff --git a/packages/grpc-native-core/test/prototype_pollution_test.js b/packages/grpc-native-core/test/prototype_pollution_test.js new file mode 100644 index 000000000..57b3d0b52 --- /dev/null +++ b/packages/grpc-native-core/test/prototype_pollution_test.js @@ -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); + }); +}); \ No newline at end of file