VYPR
Critical severity9.8NVD Advisory· Published Mar 25, 2024· Updated Apr 15, 2026

CVE-2024-29650

CVE-2024-29650

Description

An issue in @thi.ng/paths v.5.1.62 and before allows a remote attacker to execute arbitrary code via the mutIn and mutInManyUnsafe components.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@thi.ng/pathsnpm
< 5.1.635.1.63

Patches

1
c78b484882ad

fix(paths): fix #445, update toPath(), disallowProtoPath()

https://github.com/thi-ng/umbrellaKarsten SchmidtJan 30, 2024via ghsa
3 files changed · +39 19
  • packages/paths/src/mutator.ts+2 3 modified
    @@ -13,7 +13,7 @@ import type {
     	Path8,
     	PathVal,
     } from "@thi.ng/api";
    -import { disallowProtoPath, toPath } from "./path.js";
    +import { disallowProtoPath } from "./path.js";
     
     /**
      * Unchecked version of {@link defMutator}.
    @@ -72,8 +72,7 @@ export function defMutator<T, A, B, C, D, E, F, G, H>(
     	path: DeepPath<T, A, B, C, D, E, F, G, H>
     ): Fn2<T, any, any>;
     export function defMutator(path: Path): any {
    -	const ks = toPath(path);
    -	disallowProtoPath(ks);
    +	const ks = disallowProtoPath(path);
     	let [a, b, c, d] = ks;
     	switch (ks.length) {
     		case 0:
    
  • packages/paths/src/path.ts+35 16 modified
    @@ -1,12 +1,20 @@
     import type { NumOrString, Path } from "@thi.ng/api";
     import { isArray } from "@thi.ng/checks/is-array";
    +import { isNumber } from "@thi.ng/checks/is-number";
     import { isProtoPath } from "@thi.ng/checks/is-proto-path";
     import { isString } from "@thi.ng/checks/is-string";
    -import { assert } from "@thi.ng/errors/assert";
    +import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
     
     /**
      * Converts the given key path to canonical form (array).
      *
    + * @remarks
    + * If given path is an array, performs a safety check to ensure that all path
    + * items are strings or numbers and that illegal paths like `[["__proto__"],
    + * "foo"]` will be disallowed (throws an error).
    + *
    + * Also see {@link disallowProtoPath}.
    + *
      * ```
      * toPath("a.b.c");
      * // ["a", "b", "c"]
    @@ -20,16 +28,20 @@ import { assert } from "@thi.ng/errors/assert";
      *
      * @param path -
      */
    -export const toPath = (path: Path): readonly NumOrString[] =>
    -	isArray(path)
    -		? <any[]>path
    -		: isString(path)
    -		? path.length > 0
    -			? path.split(".")
    -			: []
    -		: path != null
    -		? [path]
    -		: [];
    +export const toPath = (path: Path): readonly NumOrString[] => {
    +	if (isArray(path)) {
    +		if (!path.every((x) => isString(x) || isNumber(x))) __illegal(path);
    +		return <any[]>path;
    +	} else {
    +		return isString(path)
    +			? path.length > 0
    +				? path.split(".")
    +				: []
    +			: path != null
    +			? <any[]>[path]
    +			: [];
    +	}
    +};
     
     /**
      * Takes an arbitrary object and lookup path. Descends into object along
    @@ -59,10 +71,11 @@ export const exists = (obj: any, path: Path) => {
     };
     
     /**
    - * Helper function to analyze given `path` using
    + * Helper function. First converts given `path` using {@link toPath} and then
    + * analyzes it via
      * [`isProtoPath()`](https://docs.thi.ng/umbrella/checks/functions/isProtoPath.html).
      * Throws an error if path contains any property which might lead to prototype
    - * poisoning.
    + * poisoning. Returns converted path if valid.
      *
      * @remarks
      * The following properties are considered illegal.
    @@ -73,6 +86,12 @@ export const exists = (obj: any, path: Path) => {
      *
      * @param path -
      */
    -export const disallowProtoPath = (path: Path) => (
    -	assert(!isProtoPath(path), `unsafe path: '${path}'`), path
    -);
    +export const disallowProtoPath = (path: Path): readonly NumOrString[] => {
    +	const $path = toPath(path);
    +	if (isProtoPath($path)) __illegal(path);
    +	return $path;
    +};
    +
    +/** @internal */
    +const __illegal = (path: any) =>
    +	illegalArgs(`illegal path: ${JSON.stringify(path)}`);
    
  • packages/paths/test/main.test.ts+2 0 modified
    @@ -170,4 +170,6 @@ test("exists", () => {
     test("mutIn", () => {
     	const a: any = {};
     	expect(() => mutIn(a, ["__proto__", "polluted"], true)).toThrow();
    +	expect(() => mutIn(a, <any>[["__proto__"], "polluted"], true)).toThrow();
    +	expect(() => mutIn(a, <any>[[["__proto__"]], "polluted"], true)).toThrow();
     });
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.