ueberdb2 4.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Notable Changes
2
2
 
3
+ ## v4.0.1
4
+
5
+ Security fix:
6
+
7
+ * `getSub()` now returns `null` when it encounters a non-"own" property
8
+ (including `__proto__`) or any non-object while walking the given property
9
+ path. This should make it easier to avoid accidental prototype pollution
10
+ vulnerabilities.
11
+
3
12
  ## v4.0.0
4
13
 
5
14
  Compatibility changes:
@@ -19,6 +28,15 @@ Updated database dependencies:
19
28
 
20
29
  * `redis`: Updated `redis` from 3.1.2 to 4.1.0.
21
30
 
31
+ ## v3.0.2
32
+
33
+ Security fix:
34
+
35
+ * `getSub()` now returns `null` when it encounters a non-"own" property
36
+ (including `__proto__`) or any non-object while walking the given property
37
+ path. This should make it easier to avoid accidental prototype pollution
38
+ vulnerabilities.
39
+
22
40
  ## v3.0.1
23
41
 
24
42
  Bug fixes:
@@ -57,6 +75,15 @@ Updated database dependencies:
57
75
  * `postgres`: Updated `pg` to 8.7.3.
58
76
  * `sqlite`: Updated `sqlite3` to 5.0.6.
59
77
 
78
+ ## v2.2.4
79
+
80
+ Security fix:
81
+
82
+ * `getSub()` now returns `null` when it encounters a non-"own" property
83
+ (including `__proto__`) or any non-object while walking the given property
84
+ path. This should make it easier to avoid accidental prototype pollution
85
+ vulnerabilities.
86
+
60
87
  ## v2.2.0
61
88
 
62
89
  Compatibility changes:
@@ -508,33 +508,27 @@ exports.Database = class {
508
508
  * "bla"]
509
509
  */
510
510
  async getSub(key, sub) {
511
- let subvalue;
512
511
  await this._lock(key);
513
512
  try {
514
- // get the full value
515
- const value = await this._getLocked(key);
516
-
517
- // everything is correct, navigate to the subvalue and return it
518
- subvalue = value;
519
-
520
- for (let i = 0; i < sub.length; i++) {
521
- // test if the subvalue exist
522
- if (subvalue != null && subvalue[sub[i]] !== undefined) {
523
- subvalue = subvalue[sub[i]];
524
- } else {
525
- // the subvalue doesn't exist, break the loop and return null
526
- subvalue = null;
527
- break;
513
+ let v = await this._getLocked(key);
514
+ for (const k of sub) {
515
+ if (typeof v !== 'object' || (v != null && !Object.prototype.hasOwnProperty.call(v, k)) ||
516
+ // __proto__ is not an "own" property but we check for it explicitly for added safety,
517
+ // to improve readability, and to help static code analysis tools rule out prototype
518
+ // pollution vulnerabilities.
519
+ k === '__proto__') {
520
+ v = null;
528
521
  }
522
+ if (v == null) break;
523
+ v = v[k];
529
524
  }
530
-
531
525
  if (this.logger.isDebugEnabled()) {
532
- this.logger.debug(`GETSUB - ${key}${JSON.stringify(sub)} - ${JSON.stringify(subvalue)}`);
526
+ this.logger.debug(`GETSUB - ${key}${JSON.stringify(sub)} - ${JSON.stringify(v)}`);
533
527
  }
528
+ return clone(v);
534
529
  } finally {
535
530
  this._unlock(key);
536
531
  }
537
- return clone(subvalue);
538
532
  }
539
533
 
540
534
  /**
package/package.json CHANGED
@@ -51,7 +51,7 @@
51
51
  "url": "https://github.com/ether/ueberDB.git"
52
52
  },
53
53
  "main": "./index",
54
- "version": "4.0.0",
54
+ "version": "4.0.1",
55
55
  "bugs": {
56
56
  "url": "https://github.com/ether/ueberDB/issues"
57
57
  },
@@ -0,0 +1,31 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert').strict;
4
+ const ueberdb = require('../index');
5
+
6
+ describe(__filename, function () {
7
+ let db;
8
+
9
+ beforeEach(async function () {
10
+ db = new ueberdb.Database('memory', {}, {});
11
+ await db.init();
12
+ await db.set('k', {s: 'v'});
13
+ });
14
+
15
+ afterEach(async function () {
16
+ if (db != null) await db.close();
17
+ db = null;
18
+ });
19
+
20
+ it('getSub stops at non-objects', async function () {
21
+ assert(await db.getSub('k', ['s', 'length']) == null);
22
+ });
23
+
24
+ it('getSub ignores non-own properties', async function () {
25
+ assert(await db.getSub('k', ['toString']) == null);
26
+ });
27
+
28
+ it('getSub ignores __proto__', async function () {
29
+ assert(await db.getSub('k', ['__proto__']) == null);
30
+ });
31
+ });
@@ -4,9 +4,19 @@ const assert = require('assert').strict;
4
4
  const ueberdb = require('../index');
5
5
 
6
6
  describe(__filename, function () {
7
- it('setSub rejects __proto__', async function () {
8
- const db = new ueberdb.Database('memory', {}, {});
7
+ let db;
8
+
9
+ beforeEach(async function () {
10
+ db = new ueberdb.Database('memory', {}, {});
9
11
  await db.init();
12
+ });
13
+
14
+ afterEach(async function () {
15
+ if (db != null) await db.close();
16
+ db = null;
17
+ });
18
+
19
+ it('setSub rejects __proto__', async function () {
10
20
  await db.set('k', {});
11
21
  await assert.rejects(db.setSub('k', ['__proto__'], 'v'));
12
22
  });