shelving 1.267.2 → 1.267.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shelving",
3
- "version": "1.267.2",
3
+ "version": "1.267.3",
4
4
  "author": "Dave Houlbrooke <dave@shax.com>",
5
5
  "repository": {
6
6
  "type": "git",
@@ -163,6 +163,7 @@ export declare const omitDictionaryItem: <T>(dict: ImmutableDictionary<T>, key:
163
163
  export declare const pickDictionaryItems: <T>(dict: ImmutableDictionary<T>, ...keys: string[]) => ImmutableDictionary<T>;
164
164
  /**
165
165
  * Set a single named item on a dictionary object (by reference) and return its value.
166
+ * - The key is trusted by contract: a runtime-untrusted key like `"__proto__"` would mutate the target's prototype, so validate or filter untrusted keys before calling (or use a null-prototype target).
166
167
  *
167
168
  * @param dict The dictionary to set the item on (modified by reference).
168
169
  * @param key The key of the item to set.
@@ -173,6 +174,7 @@ export declare const pickDictionaryItems: <T>(dict: ImmutableDictionary<T>, ...k
173
174
  export declare const setDictionaryItem: <T>(dict: MutableDictionary<T>, key: string, value: T) => T;
174
175
  /**
175
176
  * Set several named items on a dictionary object (by reference).
177
+ * - Keys are trusted by contract: a runtime-untrusted key like `"__proto__"` would mutate the target's prototype, so validate or filter untrusted keys before calling (or use a null-prototype target).
176
178
  *
177
179
  * @param dict The dictionary to set the items on (modified by reference).
178
180
  * @param entries The items to set, as a dictionary or iterable set of key/value entry tuples.
@@ -139,6 +139,7 @@ export const omitDictionaryItem = omitProps;
139
139
  export const pickDictionaryItems = pickProps;
140
140
  /**
141
141
  * Set a single named item on a dictionary object (by reference) and return its value.
142
+ * - The key is trusted by contract: a runtime-untrusted key like `"__proto__"` would mutate the target's prototype, so validate or filter untrusted keys before calling (or use a null-prototype target).
142
143
  *
143
144
  * @param dict The dictionary to set the item on (modified by reference).
144
145
  * @param key The key of the item to set.
@@ -149,6 +150,7 @@ export const pickDictionaryItems = pickProps;
149
150
  export const setDictionaryItem = setProp;
150
151
  /**
151
152
  * Set several named items on a dictionary object (by reference).
153
+ * - Keys are trusted by contract: a runtime-untrusted key like `"__proto__"` would mutate the target's prototype, so validate or filter untrusted keys before calling (or use a null-prototype target).
152
154
  *
153
155
  * @param dict The dictionary to set the items on (modified by reference).
154
156
  * @param entries The items to set, as a dictionary or iterable set of key/value entry tuples.
package/util/diff.d.ts CHANGED
@@ -44,6 +44,7 @@ export declare function deepDiffArray<R extends ImmutableArray>(left: ImmutableA
44
44
  * @returns Object containing the missing/updated properties that `left` needs to become `right`.
45
45
  * - If the two values are deeply equal the `SAME` constant is returned.
46
46
  * - If `left` isn't an object then the result can't be diffed so entire `right` is returned.
47
+ * - Diff object has a `null` prototype, so an untrusted `"__proto__"` key in `right` becomes an inert own property instead of injecting a prototype.
47
48
  * @see https://shelving.cc/util/diff/deepDiffObject
48
49
  */
49
50
  export declare function deepDiffObject<R extends ImmutableObject>(left: ImmutableObject, right: R): R | DeepPartial<R> | typeof SAME;
package/util/diff.js CHANGED
@@ -42,7 +42,10 @@ export function deepDiffObject(left, right) {
42
42
  // If left is empty, entire right is returned.
43
43
  if (!leftKeys.length)
44
44
  return rightKeys.length ? right : SAME;
45
- const diff = {};
45
+ // Null-prototype accumulator: an untrusted `"__proto__"` key in `right` then becomes an inert own property
46
+ // instead of invoking the inherited `__proto__` setter, so a crafted `{ "__proto__": … }` input can't reassign
47
+ // the diff object's prototype.
48
+ const diff = Object.create(null);
46
49
  let changed = false;
47
50
  for (const k of rightKeys) {
48
51
  const d = deepDiff(left[k], right[k]);
package/util/merge.d.ts CHANGED
@@ -67,6 +67,7 @@ export declare function mergeArray<L, R>(left: ImmutableArray<L>, right: Immutab
67
67
  * - Only works on enumerable own keys (as returned by `Object.keys()`).
68
68
  * - Always returns a new object (or the `left` object if no changes were made).
69
69
  * - Resulting object is `cleaned`, i.e. properties in `left` or `right` that are `undefined` will be removed from the merged object.
70
+ * - Merged object has a `null` prototype, so an untrusted `"__proto__"` key in `right` becomes an inert own property instead of injecting a prototype.
70
71
  *
71
72
  * @param left The left object to merge into.
72
73
  * @param right The right object whose props replace or merge with `left`.
package/util/merge.js CHANGED
@@ -45,7 +45,10 @@ export function mergeObject(left, right, recursor = exactMerge) {
45
45
  if (!rightEntries.length)
46
46
  return left;
47
47
  const leftKeys = Object.keys(left);
48
- const merged = { ...left };
48
+ // Null-prototype accumulator: an untrusted `"__proto__"` key in `right` then becomes an inert own property
49
+ // instead of invoking the inherited `__proto__` setter, so a crafted `{ "__proto__": … }` input can't reassign
50
+ // the merged object's prototype.
51
+ const merged = Object.assign(Object.create(null), left);
49
52
  let changed = false;
50
53
  for (const [k, r] of rightEntries) {
51
54
  if (leftKeys.includes(k)) {
package/util/object.d.ts CHANGED
@@ -249,6 +249,7 @@ export declare const omitProp: <T, K extends Key<T>>(input: T, key: K) => Omit<T
249
249
  export declare function pickProps<T, K extends Key<T>>(obj: T, ...keys: K[]): Pick<T, K>;
250
250
  /**
251
251
  * Set a single named prop on an object (by reference) and return its value.
252
+ * - The key is trusted by contract: a runtime-untrusted key like `"__proto__"` would mutate the target's prototype, so validate or filter untrusted keys before calling (or use a null-prototype target).
252
253
  *
253
254
  * @param obj The object to set the prop on (modified by reference).
254
255
  * @param key The key of the prop to set.
@@ -259,6 +260,7 @@ export declare function pickProps<T, K extends Key<T>>(obj: T, ...keys: K[]): Pi
259
260
  export declare function setProp<T extends MutableObject, K extends Key<T>>(obj: T, key: K, value: T[K]): T[K];
260
261
  /**
261
262
  * Set several named props on an object (by reference).
263
+ * - Keys are trusted by contract: a runtime-untrusted key like `"__proto__"` would mutate the target's prototype, so validate or filter untrusted keys before calling (or use a null-prototype target).
262
264
  *
263
265
  * @param obj The object to set the props on (modified by reference).
264
266
  * @param entries The props to set, as an object or iterable set of key/value entry tuples.
package/util/object.js CHANGED
@@ -157,6 +157,7 @@ function _hasKey([key]) {
157
157
  }
158
158
  /**
159
159
  * Set a single named prop on an object (by reference) and return its value.
160
+ * - The key is trusted by contract: a runtime-untrusted key like `"__proto__"` would mutate the target's prototype, so validate or filter untrusted keys before calling (or use a null-prototype target).
160
161
  *
161
162
  * @param obj The object to set the prop on (modified by reference).
162
163
  * @param key The key of the prop to set.
@@ -170,6 +171,7 @@ export function setProp(obj, key, value) {
170
171
  }
171
172
  /**
172
173
  * Set several named props on an object (by reference).
174
+ * - Keys are trusted by contract: a runtime-untrusted key like `"__proto__"` would mutate the target's prototype, so validate or filter untrusted keys before calling (or use a null-prototype target).
173
175
  *
174
176
  * @param obj The object to set the props on (modified by reference).
175
177
  * @param entries The props to set, as an object or iterable set of key/value entry tuples.
package/util/uri.d.ts CHANGED
@@ -192,6 +192,7 @@ export type PossibleURIParams = PossibleURI | URLSearchParams | ImmutableDiction
192
192
  /**
193
193
  * Get a set of params for a URI as a dictionary.
194
194
  * - Any params with `undefined` value will be ignored.
195
+ * - Returned dictionary has a `null` prototype, so an untrusted `__proto__` param becomes an inert own entry (instead of being silently dropped by the inherited `__proto__` setter).
195
196
  *
196
197
  * @param params Possible URI params to convert.
197
198
  * @param caller Function to attribute a thrown error to (defaults to `getURIParams` itself).
package/util/uri.js CHANGED
@@ -99,6 +99,7 @@ function* getURIEntries(params, caller = getURIParams) {
99
99
  /**
100
100
  * Get a set of params for a URI as a dictionary.
101
101
  * - Any params with `undefined` value will be ignored.
102
+ * - Returned dictionary has a `null` prototype, so an untrusted `__proto__` param becomes an inert own entry (instead of being silently dropped by the inherited `__proto__` setter).
102
103
  *
103
104
  * @param params Possible URI params to convert.
104
105
  * @param caller Function to attribute a thrown error to (defaults to `getURIParams` itself).
@@ -108,7 +109,9 @@ function* getURIEntries(params, caller = getURIParams) {
108
109
  * @see https://shelving.cc/util/uri/getURIParams
109
110
  */
110
111
  export function getURIParams(params, caller = getURIParams) {
111
- const output = {};
112
+ // Null-prototype accumulator: param keys are runtime-untrusted, so an untrusted `"__proto__"` key becomes an
113
+ // inert own entry instead of invoking the inherited `__proto__` setter (which would silently drop the param).
114
+ const output = Object.create(null);
112
115
  for (const [key, str] of getURIEntries(params, caller))
113
116
  output[key] = str;
114
117
  return output;