utils.test.js
4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
'use strict';
const utils = require('../lib/utils');
const assert = require('assert');
const debug = require('debug');
let mongo;
try {
mongo = new require('mongodb');
} catch (e) {
debug('mongo', 'cannot construct mongodb instance');
}
describe('lib/utils', function() {
describe('clone', function() {
it('clones constructors named ObjectId', function(done) {
function ObjectId(id) {
this.id = id;
}
const o1 = new ObjectId('1234');
const o2 = utils.clone(o1);
assert.ok(o2 instanceof ObjectId);
done();
});
it('clones constructors named ObjectID', function(done) {
function ObjectID(id) {
this.id = id;
}
const o1 = new ObjectID('1234');
const o2 = utils.clone(o1);
assert.ok(o2 instanceof ObjectID);
done();
});
it('clones RegExp', function(done) {
const sampleRE = /a/giy;
const clonedRE = utils.clone(sampleRE);
assert.ok(clonedRE !== sampleRE);
assert.ok(clonedRE instanceof RegExp);
assert.ok(clonedRE.source === 'a');
assert.ok(clonedRE.flags === 'giy');
done();
});
it('clones Buffer', function(done) {
const buf1 = Buffer.alloc(10);
const buf2 = utils.clone(buf1);
assert.ok(buf2 instanceof Buffer);
done();
});
it('does not clone constructors named ObjectIdd', function(done) {
function ObjectIdd(id) {
this.id = id;
}
const o1 = new ObjectIdd('1234');
const o2 = utils.clone(o1);
assert.ok(!(o2 instanceof ObjectIdd));
done();
});
it('optionally clones ObjectId constructors using its clone method', function(done) {
function ObjectID(id) {
this.id = id;
this.cloned = false;
}
ObjectID.prototype.clone = function() {
const ret = new ObjectID(this.id);
ret.cloned = true;
return ret;
};
const id = 1234;
const o1 = new ObjectID(id);
assert.equal(id, o1.id);
assert.equal(false, o1.cloned);
const o2 = utils.clone(o1);
assert.ok(o2 instanceof ObjectID);
assert.equal(id, o2.id);
assert.ok(o2.cloned);
done();
});
it('clones mongodb.ReadPreferences', function(done) {
if (!mongo) return done();
const tags = [
{ dc: 'tag1' }
];
const prefs = [
new mongo.ReadPreference('primary'),
new mongo.ReadPreference(mongo.ReadPreference.PRIMARY_PREFERRED),
new mongo.ReadPreference('secondary', tags)
];
const prefsCloned = utils.clone(prefs);
for (let i = 0; i < prefsCloned.length; i++) {
assert.notEqual(prefs[i], prefsCloned[i]);
if (prefs[i].tags) {
assert.ok(prefsCloned[i].tags);
assert.notEqual(prefs[i].tags, prefsCloned[i].tags);
assert.notEqual(prefs[i].tags[0], prefsCloned[i].tags[0]);
} else {
assert.equal(prefsCloned[i].tags, null);
}
}
done();
});
it('clones mongodb.Binary', function(done) {
if (!mongo) return done();
const buf = Buffer.from('hi');
const binary = new mongo.Binary(buf, 2);
const clone = utils.clone(binary);
assert.equal(binary.sub_type, clone.sub_type);
assert.equal(String(binary.buffer), String(buf));
assert.ok(binary !== clone);
done();
});
it('handles objects with no constructor', function(done) {
const name = '335';
const o = Object.create(null);
o.name = name;
let clone;
assert.doesNotThrow(function() {
clone = utils.clone(o);
});
assert.equal(name, clone.name);
assert.ok(o != clone);
done();
});
it('handles buffers', function(done) {
const buff = Buffer.alloc(10);
buff.fill(1);
const clone = utils.clone(buff);
for (let i = 0; i < buff.length; i++) {
assert.equal(buff[i], clone[i]);
}
done();
});
it('skips __proto__', function() {
const payload = JSON.parse('{"__proto__": {"polluted": "vulnerable"}}');
const res = utils.clone(payload);
assert.strictEqual({}.polluted, void 0);
assert.strictEqual(res.__proto__, Object.prototype);
});
});
describe('merge', function() {
it('avoids prototype pollution', function() {
const payload = JSON.parse('{"__proto__": {"polluted": "vulnerable"}}');
const obj = {};
utils.merge(obj, payload);
assert.strictEqual({}.polluted, void 0);
});
});
});