Skip to content

Commit

Permalink
Remove object path functions.
Browse files Browse the repository at this point in the history
- Remove `util.getPath`, `util.setPath`, and `util.deletePath`.
- These are unused in `forge` itself.
- Path processing has potential security issues. (For `setPath` in
  particular).
- `lodash` has better replacements: `get`, `set`, and `unset`.
- See also:
  - CHANGELOG.md 0.9.2 entry.
  - https://snyk.io/vuln/SNYK-JS-NODEFORGE-598677
  - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7720
  • Loading branch information
davidlehn committed Sep 2, 2020
1 parent 30d560c commit 6a1e3ef
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 100 deletions.
15 changes: 13 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
Forge ChangeLog
===============

### Changed
- **BREAKING**: Node.js 4 no longer supported. The code *may* still work, and
non-invasive patches to keep it working will be considered. However, more
modern tools no longer support very old Node.js versions making testing
difficult.
modern tools no longer support old Node.js versions making testing difficult.

### Removed
- **BREAKING**: Remove `util.getPath`, `util.setPath`, and `util.deletePath`.
`util.setPath` had a potential prototype pollution security issue when used
with unsafe inputs. These functions are not used by `forge` itself. They date
from an early time when `forge` was targeted at providing general helper
functions. The library direction changed to be more focused on cryptography.
Many other excellent libraries are more suitable for general utilities. If
you need a replacement for these functions, consier `get`, `set`, and `unset`
from [lodash](https://lodash.com/). But also consider the potential similar
security issues with those APIs.

## 0.9.2 - 2019-09-01

Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2035,8 +2035,6 @@ When using this code please keep the following in mind:
- Certain features in this library are less susceptible to attacks depending on
usage. This primarily includes features that deal with data format
manipulation or those that are not involved in communication.
- Do not pass unsafe inputs to `util.setPath`. Doing so could expose a
prototype pollution security issue.

Library Background
------------------
Expand Down
96 changes: 0 additions & 96 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -2513,102 +2513,6 @@ util.makeLink = function(path, query, fragment) {
((fragment.length > 0) ? ('#' + fragment) : '');
};

/**
* Follows a path of keys deep into an object hierarchy and set a value.
* If a key does not exist or it's value is not an object, create an
* object in it's place. This can be destructive to a object tree if
* leaf nodes are given as non-final path keys.
* Used to avoid exceptions from missing parts of the path.
*
* SECURITY NOTE: Do not use unsafe inputs. Doing so could expose a prototype
* pollution security issue.
*
* @param object the starting object.
* @param keys an array of string keys.
* @param value the value to set.
*/
util.setPath = function(object, keys, value) {
// need to start at an object
if(typeof(object) === 'object' && object !== null) {
var i = 0;
var len = keys.length;
while(i < len) {
var next = keys[i++];
if(i == len) {
// last
object[next] = value;
} else {
// more
var hasNext = (next in object);
if(!hasNext ||
(hasNext && typeof(object[next]) !== 'object') ||
(hasNext && object[next] === null)) {
object[next] = {};
}
object = object[next];
}
}
}
};

/**
* Follows a path of keys deep into an object hierarchy and return a value.
* If a key does not exist, create an object in it's place.
* Used to avoid exceptions from missing parts of the path.
*
* @param object the starting object.
* @param keys an array of string keys.
* @param _default value to return if path not found.
*
* @return the value at the path if found, else default if given, else
* undefined.
*/
util.getPath = function(object, keys, _default) {
var i = 0;
var len = keys.length;
var hasNext = true;
while(hasNext && i < len &&
typeof(object) === 'object' && object !== null) {
var next = keys[i++];
hasNext = next in object;
if(hasNext) {
object = object[next];
}
}
return (hasNext ? object : _default);
};

/**
* Follow a path of keys deep into an object hierarchy and delete the
* last one. If a key does not exist, do nothing.
* Used to avoid exceptions from missing parts of the path.
*
* @param object the starting object.
* @param keys an array of string keys.
*/
util.deletePath = function(object, keys) {
// need to start at an object
if(typeof(object) === 'object' && object !== null) {
var i = 0;
var len = keys.length;
while(i < len) {
var next = keys[i++];
if(i == len) {
// last
delete object[next];
} else {
// more
if(!(next in object) ||
(typeof(object[next]) !== 'object') ||
(object[next] === null)) {
break;
}
object = object[next];
}
}
}
};

/**
* Check if an object is empty.
*
Expand Down

0 comments on commit 6a1e3ef

Please sign in to comment.