Skip to content

Commit 1d40aa6

Browse files
committed
fix: prevent prototype pollutions
1 parent de526c1 commit 1d40aa6

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

src/Collection.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import { hasOwn, isPlainObject } from '../lib/utils.js';
99
* @private
1010
* @type {object}
1111
*/
12-
const observers = {};
12+
const observers = Object.create(null);
1313
/**
1414
* @private
1515
* @type {object}
1616
*/
17-
const observersByComp = {};
17+
const observersByComp = Object.create(null);
1818
/**
1919
* Get the list of callbacks for changes on a collection
2020
* @param {string} type - Type of change happening.
@@ -45,7 +45,7 @@ export function getObservers(type, collection, newDocument) {
4545
});
4646
}
4747
// Find the observers related to the specific query
48-
if (observersByComp[collection]) {
48+
if (observersByComp[collection] && !(collection in {})) {
4949
let keys = Object.keys(observersByComp[collection]);
5050
for (let i = 0; i < keys.length; i++) {
5151
observersByComp[collection][keys[i]].callbacks.forEach(
@@ -243,14 +243,16 @@ export class Collection {
243243
// collection is changed it needs to be re-run
244244
if (Tracker.active && Tracker.currentComputation) {
245245
let id = Tracker.currentComputation._id;
246-
observersByComp[this._name] = observersByComp[this._name] || {};
246+
observersByComp[this._name] =
247+
observersByComp[this._name] || Object.create(null);
247248
if (!observersByComp[this._name][id]) {
248249
let item = {
249250
computation: Tracker.currentComputation,
250251
callbacks: [],
251252
};
252253
observersByComp[this._name][id] = item;
253254
}
255+
254256
let item = observersByComp[this._name][id];
255257

256258
item.callbacks.push({

test/src/Collection.tests.js

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,20 @@ describe('Collection', function () {
210210
done();
211211
});
212212
});
213+
it('triggers a reactive observer', (done) => {
214+
const collectionName = Random.id(6);
215+
const c = new Mongo.Collection(collectionName);
216+
217+
Tracker.autorun((comp) => {
218+
const doc = c.findOne({ foo: 1 });
219+
if (doc) {
220+
comp.stop();
221+
done();
222+
}
223+
});
224+
225+
setTimeout(() => c.insert({ foo: 1 }), 50);
226+
});
213227
it('does not imply prototype pollution', (done) => {
214228
const collectionName = Random.id(6);
215229
const c = new Mongo.Collection(collectionName);
@@ -221,15 +235,29 @@ describe('Collection', function () {
221235
});
222236

223237
Tracker.autorun((comp) => {
224-
const docs = c.find(insertDoc).fetch();
225-
expect(props({})).to.deep.equal(objectProps);
226-
if (docs.length > 0) {
238+
if (c.find().count() < 1) {
239+
return;
240+
}
241+
242+
c._name = '__proto__';
243+
try {
244+
c.find(insertDoc);
245+
} catch {}
246+
try {
247+
expect(props({})).to.deep.equal(objectProps);
248+
} catch (e) {
227249
comp.stop();
228-
done();
250+
return done(e);
229251
}
252+
253+
comp.stop();
254+
done();
230255
});
231256

232-
setTimeout(() => c.insert(insertDoc), 50);
257+
setTimeout(() => {
258+
c._name = collectionName;
259+
c.insert(insertDoc);
260+
}, 50);
233261
});
234262
});
235263

0 commit comments

Comments
 (0)