$ debdiff ../node-lodash_4.17.21+dfsg+\~cs8.31.198.20210220-9.dsc ../node-lodash_4.17.21+dfsg+\~cs8.31.198.20210220-9+deb12u1.dsc diff -Nru node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/changelog node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/changelog --- node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/changelog 2022-05-23 21:20:01.000000000 +0530 +++ node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/changelog 2026-07-05 02:41:49.000000000 +0530 @@ -1,3 +1,20 @@ +node-lodash (4.17.21+dfsg+~cs8.31.198.20210220-9+deb12u1) bookworm; urgency=high + + * Non-maintainer upload by the LTS team. + * Add patch to prevent prototype pollution on baseUnset function. + (Fixes: CVE-2025-13465) (Closes: #1126265) + * Add patch to block prototype pollution in baseUnset via + constructor/prototype traversal (array-wrapped path bypass of the + CVE-2025-13465 fix). (Fixes: CVE-2026-2950) + * Add patch to validate imports keys in _.template, preventing code + injection via the Function() sink. (Fixes: CVE-2026-4800) + * Add patch to update lodash-cli dependency map so the regenerated + lodash.template module requires assignWith/arrayEach; without it the + module throws "assignWith is not defined" at runtime (caught by the + node-gulp-util autopkgtest). (Related: CVE-2026-4800) + + -- Utkarsh Gupta Sun, 05 Jul 2026 02:41:49 +0530 + node-lodash (4.17.21+dfsg+~cs8.31.198.20210220-9) unstable; urgency=medium * Team upload diff -Nru node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2025-13465.patch node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2025-13465.patch --- node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2025-13465.patch 1970-01-01 05:30:00.000000000 +0530 +++ node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2025-13465.patch 2026-07-05 02:41:49.000000000 +0530 @@ -0,0 +1,116 @@ +From edadd452146f7e4bad4ea684e955708931d84d81 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= +Date: Fri, 5 Dec 2025 19:26:49 +0100 +Subject: [PATCH] Prevent prototype pollution on baseUnset function + +* test: add tests to prevent security regressions + +* sec: prevent prototype pollution on `baseUnset` function + +* chore: improve security patch + +- Expand both `_.omit` & `_.unset` security tests to loop over `__proto__`, `constructor`, `prototype` +- Only block `__proto__` if not an own property +--- + lodash.js | 43 ++++++++++++++++- + test/test.js | 30 ++++++++++++ + 2 files changed, 71 insertions(+), 2 deletions(-) + +--- a/lodash.js ++++ b/lodash.js +@@ -4373,8 +4373,47 @@ + */ + function baseUnset(object, path) { + path = castPath(path, object); +- object = parent(object, path); +- return object == null || delete object[toKey(last(path))]; ++ ++ // Prevent prototype pollution, see: https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg ++ var index = -1, ++ length = path.length; ++ ++ if (!length) { ++ return true; ++ } ++ ++ var isRootPrimitive = object == null || (typeof object !== 'object' && typeof object !== 'function'); ++ ++ while (++index < length) { ++ var key = path[index]; ++ ++ // skip non-string keys (e.g., Symbols, numbers) ++ if (typeof key !== 'string') { ++ continue; ++ } ++ ++ // Always block "__proto__" anywhere in the path if it's not expected ++ if (key === '__proto__' && !hasOwnProperty.call(object, '__proto__')) { ++ return false; ++ } ++ ++ // Block "constructor.prototype" chains ++ if (key === 'constructor' && ++ (index + 1) < length && ++ typeof path[index + 1] === 'string' && ++ path[index + 1] === 'prototype') { ++ ++ // Allow ONLY when the path starts at a primitive root, e.g., _.unset(0, 'constructor.prototype.a') ++ if (isRootPrimitive && index === 0) { ++ continue; ++ } ++ ++ return false; ++ } ++ } ++ ++ var obj = parent(object, path); ++ return obj == null || delete obj[toKey(last(path))]; + } + + /** +--- a/test/test.js ++++ b/test/test.js +@@ -16573,6 +16573,21 @@ + assert.deepEqual(object, { 'a': { 'b': 2 } }); + }); + }); ++ ++ // Prevent regression for https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg ++ QUnit.test('Security: _.omit should not allow modifying prototype or constructor properties', function(assert) { ++ assert.expect(3); ++ ++ var testObj1 = {}; ++ assert.strictEqual(typeof testObj1.toString, 'function', 'Object.toString should work before omit'); ++ ++ _.omit({}, ['__proto__.toString']); ++ _.omit({}, ['constructor.prototype.toString']); ++ ++ var testObj2 = {}; ++ assert.strictEqual(typeof testObj2.toString, 'function', 'Object.toString should still work after omit'); ++ assert.strictEqual(Object.prototype.toString.call({}), '[object Object]', 'Object.toString should behave as expected'); ++ }); + }()); + + /*--------------------------------------------------------------------------*/ +@@ -25239,6 +25254,21 @@ + skipAssert(assert); + } + }); ++ ++ // Prevent regression for https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg ++ QUnit.test('Security: _.unset should not allow modifying prototype or constructor properties', function(assert) { ++ assert.expect(3); ++ ++ var testStr1 = 'ABC'; ++ assert.strictEqual(typeof testStr1.toLowerCase, 'function', 'String.toLowerCase should exist before unset'); ++ ++ _.unset({ foo: 'bar' }, 'foo.__proto__.toLowerCase'); ++ _.unset({ foo: 'bar' }, 'foo.constructor.prototype.toLowerCase'); ++ ++ var testStr2 = 'ABC'; ++ assert.strictEqual(typeof testStr2.toLowerCase, 'function', 'String.toLowerCase should still exist after unset'); ++ assert.strictEqual(testStr2.toLowerCase(), 'abc', 'String.toLowerCase should work as expected'); ++ }); + }()); + + /*--------------------------------------------------------------------------*/ diff -Nru node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-2950.patch node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-2950.patch --- node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-2950.patch 1970-01-01 05:30:00.000000000 +0530 +++ node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-2950.patch 2026-07-05 02:41:49.000000000 +0530 @@ -0,0 +1,250 @@ +Description: block prototype pollution in baseUnset via constructor/prototype + traversal. Incomplete-fix follow-up to CVE-2025-13465: the previous guard only + blocked the literal `constructor`->`prototype` two-key sequence and skipped + non-string keys, so it could be bypassed with array-wrapped path segments + (e.g. [['constructor'], ['keys']]), via constructor static methods, and from + primitive roots. Path segments are now normalized with toKey() before + validation and `constructor`/`prototype` are blocked unconditionally as + non-terminal keys. +Origin: upstream, https://github.com/lodash/lodash/commit/fe8d32eda854377349a4f922ab7655c8e5df9a0b + (test whitespace lint folded in from https://github.com/lodash/lodash/commit/1073a7693e1727e0cf3641e5f71f75ddcf8de7c0; + stale advisory-ref comments pruned per https://github.com/lodash/lodash/commit/75535f57883b7225adb96de1cfc1cd4169cfcb51) +Bug: https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh +Forwarded: not-needed +Applied-Upstream: 4.18.0 +Last-Update: 2026-06-18 +From fe8d32eda854377349a4f922ab7655c8e5df9a0b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= +Date: Mon, 30 Mar 2026 18:17:31 +0200 +Subject: [PATCH] fix: block prototype pollution in baseUnset via + constructor/prototype traversal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Block `constructor` and `prototype` unconditionally as non-terminal +traversal keys in baseUnset, matching the approach already used by +baseSet. The previous guard only blocked the specific two-key sequence +`constructor` → `prototype`, allowing attackers to: +- Delete static methods from built-in constructors (Object.keys, + Array.isArray, String.fromCharCode) via paths like + `['constructor', 'keys']` +- Delete built-in prototype methods (toFixed, toLowerCase, valueOf) + via primitive roots like `_.unset(0, 'constructor.prototype.toFixed')` +- Bypass checks entirely using array-wrapped path segments like + `[['constructor'], ['keys']]` which evaded the string-only key check +The primitive root exception that previously allowed constructor.prototype +traversal from primitives (e.g., `_.unset(0, 'constructor.prototype.a')`) +is removed as it enabled deletion of properties on shared built-in +prototypes. Path segments are now normalized with toKey() before +validation. +--- + lodash.js | 28 +++++---------- + test/test.js | 98 +++++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 98 insertions(+), 28 deletions(-) + +--- a/lodash.js ++++ b/lodash.js +@@ -4374,7 +4374,9 @@ + function baseUnset(object, path) { + path = castPath(path, object); + +- // Prevent prototype pollution, see: https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg ++ // Prevent prototype pollution: ++ // https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg ++ // https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh + var index = -1, + length = path.length; + +@@ -4382,32 +4384,17 @@ + return true; + } + +- var isRootPrimitive = object == null || (typeof object !== 'object' && typeof object !== 'function'); +- + while (++index < length) { +- var key = path[index]; +- +- // skip non-string keys (e.g., Symbols, numbers) +- if (typeof key !== 'string') { +- continue; +- } ++ var key = toKey(path[index]); + + // Always block "__proto__" anywhere in the path if it's not expected + if (key === '__proto__' && !hasOwnProperty.call(object, '__proto__')) { + return false; + } + +- // Block "constructor.prototype" chains +- if (key === 'constructor' && +- (index + 1) < length && +- typeof path[index + 1] === 'string' && +- path[index + 1] === 'prototype') { +- +- // Allow ONLY when the path starts at a primitive root, e.g., _.unset(0, 'constructor.prototype.a') +- if (isRootPrimitive && index === 0) { +- continue; +- } +- ++ // Block constructor/prototype as non-terminal traversal keys to prevent ++ // escaping the object graph into built-in constructors and prototypes. ++ if ((key === 'constructor' || key === 'prototype') && index < length - 1) { + return false; + } + } +--- a/test/test.js ++++ b/test/test.js +@@ -39,7 +39,8 @@ + funcProto = Function.prototype, + objectProto = Object.prototype, + numberProto = Number.prototype, +- stringProto = String.prototype; ++ stringProto = String.prototype, ++ booleanProto = Boolean.prototype; + + /** Method and object shortcuts. */ + var phantom = root.phantom, +@@ -16574,7 +16575,8 @@ + }); + }); + +- // Prevent regression for https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg ++ // Prevent regression for ++ // https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg + QUnit.test('Security: _.omit should not allow modifying prototype or constructor properties', function(assert) { + assert.expect(3); + +@@ -16583,10 +16585,11 @@ + + _.omit({}, ['__proto__.toString']); + _.omit({}, ['constructor.prototype.toString']); ++ _.omit({}, [['constructor'], ['prototype'], ['toString']]); + + var testObj2 = {}; + assert.strictEqual(typeof testObj2.toString, 'function', 'Object.toString should still work after omit'); +- assert.strictEqual(Object.prototype.toString.call({}), '[object Object]', 'Object.toString should behave as expected'); ++ assert.strictEqual(objectProto.toString.call({}), '[object Object]', 'Object.toString should behave as expected'); + }); + }()); + +@@ -25209,7 +25212,7 @@ + assert.deepEqual(actual, expected); + }); + +- QUnit.test('should follow `path` over non-plain objects', function(assert) { ++ QUnit.test('should block constructor.prototype paths from primitives but follow regular non-plain paths', function(assert) { + assert.expect(8); + + var object = { 'a': '' }, +@@ -25219,8 +25222,8 @@ + numberProto.a = 1; + + var actual = _.unset(0, path); +- assert.strictEqual(actual, true); +- assert.notOk('a' in numberProto); ++ assert.strictEqual(actual, false); ++ assert.ok('a' in numberProto); + + delete numberProto.a; + }); +@@ -25255,19 +25258,97 @@ + } + }); + +- // Prevent regression for https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg ++ // Prevent regression for: ++ // https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg ++ // https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh + QUnit.test('Security: _.unset should not allow modifying prototype or constructor properties', function(assert) { +- assert.expect(3); ++ assert.expect(6); + + var testStr1 = 'ABC'; + assert.strictEqual(typeof testStr1.toLowerCase, 'function', 'String.toLowerCase should exist before unset'); + + _.unset({ foo: 'bar' }, 'foo.__proto__.toLowerCase'); + _.unset({ foo: 'bar' }, 'foo.constructor.prototype.toLowerCase'); ++ _.unset({ foo: 'bar' }, [['foo'], ['__proto__'], ['toLowerCase']]); ++ _.unset({ foo: 'bar' }, [['foo'], ['constructor'], ['prototype'], ['toLowerCase']]); ++ _.unset({ foo: 'bar' }, ['foo', ['__proto__'], 'toLowerCase']); + + var testStr2 = 'ABC'; + assert.strictEqual(typeof testStr2.toLowerCase, 'function', 'String.toLowerCase should still exist after unset'); + assert.strictEqual(testStr2.toLowerCase(), 'abc', 'String.toLowerCase should work as expected'); ++ ++ objectProto.foo = 'bar'; ++ _.unset({}, [['__proto__'], ['foo']]); ++ assert.strictEqual(objectProto.foo, 'bar', '__proto__ access via array-wrapped segments should be blocked'); ++ delete objectProto.foo; ++ ++ assert.strictEqual(typeof funcProto.apply, 'function', 'Function.prototype.apply should exist before unset'); ++ ++ _.unset(0, 'constructor.prototype.toString.constructor.prototype.apply'); ++ _.unset(0, ['constructor', 'prototype', 'toString', 'constructor', 'prototype', 'apply']); ++ ++ assert.strictEqual(typeof funcProto.apply, 'function', 'Function.prototype.apply should not be deletable via deep constructor.prototype chain'); ++ }); ++ ++ QUnit.test('Security: _.unset should not allow deleting static methods from constructors', function(assert) { ++ assert.expect(8); ++ ++ assert.strictEqual(typeof Object.keys, 'function', 'Object.keys should exist before unset'); ++ ++ _.unset({}, ['constructor', 'keys']); ++ _.unset({}, 'constructor.keys'); ++ _.unset({}, [['constructor'], ['keys']]); ++ ++ assert.strictEqual(typeof Object.keys, 'function', 'Object.keys should not be deletable via constructor traversal'); ++ ++ assert.strictEqual(typeof Array.isArray, 'function', 'Array.isArray should exist before unset'); ++ ++ _.unset([], [ 'constructor', 'isArray']); ++ ++ assert.strictEqual(typeof Array.isArray, 'function', 'Array.isArray should not be deletable via constructor traversal'); ++ ++ assert.strictEqual(typeof String.fromCharCode, 'function', 'String.fromCharCode should exist before unset'); ++ ++ _.unset('', [ 'constructor', 'fromCharCode']); ++ _.unset({ foo: 'bar' }, ['foo', 'constructor', 'fromCharCode']); ++ ++ assert.strictEqual(typeof String.fromCharCode, 'function', 'String.fromCharCode should not be deletable via constructor traversal'); ++ ++ assert.strictEqual(typeof Number.isFinite, 'function', 'Number.isFinite should exist before unset'); ++ ++ _.unset(0, ['constructor', 'isFinite']); ++ _.unset(0, 'constructor.isFinite'); ++ ++ assert.strictEqual(typeof Number.isFinite, 'function', 'Number.isFinite should not be deletable via primitive constructor traversal'); ++ }); ++ ++ // Prevent regression for: ++ // https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh ++ QUnit.test('Security: _.unset should protect built-in prototype methods on primitive types', function(assert) { ++ assert.expect(11); ++ ++ // Number.prototype built-ins ++ assert.strictEqual(typeof numberProto.toFixed, 'function', 'Number.prototype.toFixed should exist before unset'); ++ ++ assert.strictEqual(_.unset(0, 'constructor.prototype.toFixed'), false, 'should return false for built-in Number.prototype.toFixed'); ++ assert.strictEqual(_.unset(0, ['constructor', 'prototype', 'toFixed']), false, 'should return false for built-in Number.prototype.toFixed (array path)'); ++ assert.strictEqual(_.unset(0, ['constructor', ['prototype'], 'toFixed']), false, 'should return false for built-in Number.prototype.toFixed (array path)'); ++ ++ assert.strictEqual(typeof numberProto.toFixed, 'function', 'Number.prototype.toFixed should still exist after unset attempts'); ++ ++ // String.prototype built-ins ++ assert.strictEqual(typeof stringProto.toLowerCase, 'function', 'String.prototype.toLowerCase should exist before unset'); ++ ++ assert.strictEqual(_.unset('', 'constructor.prototype.toLowerCase'), false, 'should return false for built-in String.prototype.toLowerCase'); ++ ++ assert.strictEqual(typeof stringProto.toLowerCase, 'function', 'String.prototype.toLowerCase should still exist after unset attempts'); ++ ++ // Boolean.prototype built-ins ++ assert.strictEqual(typeof booleanProto.valueOf, 'function', 'Boolean.prototype.valueOf should exist before unset'); ++ ++ assert.strictEqual(_.unset(true, 'constructor.prototype.valueOf'), false, 'should return false for built-in Boolean.prototype.valueOf'); ++ ++ assert.strictEqual(typeof booleanProto.valueOf, 'function', 'Boolean.prototype.valueOf should still exist after unset attempts'); + }); + }()); + diff -Nru node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-4800-modular-template-deps.patch node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-4800-modular-template-deps.patch --- node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-4800-modular-template-deps.patch 1970-01-01 05:30:00.000000000 +0530 +++ node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-4800-modular-template-deps.patch 2026-07-05 02:41:49.000000000 +0530 @@ -0,0 +1,25 @@ +Description: fix lodash-cli dependency map for modular _.template build. + The CVE-2026-4800 fix makes _.template use assignWith and arrayEach (and drop + assignInWith). The Debian build regenerates the standalone lodash.template + module via `lodash-cli modularize`, whose require() list is derived from this + dependency map. Without updating the map, the generated lodash.template module + fails at runtime with "ReferenceError: assignWith is not defined" (seen in the + node-gulp-util autopkgtest). This mirrors upstream's regeneration in commit + bbcb8a03deb54e2cd19f2f53e618e1fe194091bb, applied here to the CLI mapping since + Debian rebuilds the modules from source rather than shipping upstream's + pre-generated files. +Origin: vendor, Debian; corresponds to upstream https://github.com/lodash/lodash/commit/bbcb8a03deb54e2cd19f2f53e618e1fe194091bb +Bug: https://github.com/lodash/lodash/security/advisories/GHSA-r5fr-rjxr-66jc +Forwarded: not-needed +Last-Update: 2026-06-19 +--- a/lodash-cli/lib/mapping.js ++++ b/lodash-cli/lib/mapping.js +@@ -709,7 +709,7 @@ + 'takeRightWhile': ['baseWhile', 'getIteratee'], + 'takeWhile': ['baseWhile', 'getIteratee'], + 'tap': [], +- 'template': ['customDefaultsAssignIn', 'assignInWith', 'attempt', 'baseValues', 'escapeStringChar', 'isError', 'isIterateeCall', 'keys', 'toString'], ++ 'template': ['arrayEach', 'assignWith', 'customDefaultsAssignIn', 'attempt', 'baseValues', 'escapeStringChar', 'isError', 'isIterateeCall', 'keys', 'toString'], + 'throttle': ['debounce', 'isObject'], + 'thru': [], + 'times': ['baseTimes', 'getIteratee', 'toInteger'], diff -Nru node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-4800.patch node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-4800.patch --- node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-4800.patch 1970-01-01 05:30:00.000000000 +0530 +++ node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/CVE-2026-4800.patch 2026-07-05 02:41:49.000000000 +0530 @@ -0,0 +1,124 @@ +Description: validate imports keys in _.template to prevent code injection. + Incomplete-fix follow-up to CVE-2021-23337: the `variable` option was + validated against reForbiddenIdentifierChars but `imports` key names were + left unguarded, allowing arbitrary code execution via the same Function() + constructor sink at template compile time. This validates importsKeys against + reForbiddenIdentifierChars and switches assignInWith to assignWith so only + own (not inherited/prototype-polluted) keys are merged. +Origin: upstream, https://github.com/lodash/lodash/commit/879aaa93132d78c2f8d20c60279da9f8b21576d6 + (test fix folded in from https://github.com/lodash/lodash/commit/af634573030f979194871da7c68f79420992f53d; + stale advisory-ref comments corrected per https://github.com/lodash/lodash/commit/75535f57883b7225adb96de1cfc1cd4169cfcb51) +Bug: https://github.com/lodash/lodash/security/advisories/GHSA-r5fr-rjxr-66jc +Forwarded: not-needed +Applied-Upstream: 4.18.0 +Last-Update: 2026-06-19 +From 879aaa93132d78c2f8d20c60279da9f8b21576d6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= +Date: Mon, 30 Mar 2026 18:27:00 +0200 +Subject: [PATCH] fix: validate imports keys in _.template + +Fixes an incomplete patch for CVE-2021-23337. The `variable` option was validated against `reForbiddenIdentifierChars` but `importsKeys` was left unguarded, allowing code injection via the same `Function()` constructor sink. + +This patch: +1. Validates `importsKeys` against `reForbiddenIdentifierChars` +2. Replaces `assignInWith` with `assignWith` when merging imports + +Ref: https://github.com/lodash/lodash/security/advisories/GHSA-r5fr-rjxr-66jc +Ref: CVE-2026-4800 + +--------- + +Co-authored-by: Jon Church +--- + lodash.js | 13 ++++++++++--- + test/test.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 56 insertions(+), 3 deletions(-) + +--- a/lodash.js ++++ b/lodash.js +@@ -20,7 +20,8 @@ + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', + FUNC_ERROR_TEXT = 'Expected a function', +- INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`'; ++ INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`', ++ INVALID_TEMPL_IMPORTS_ERROR_TEXT = 'Invalid `imports` option passed into `_.template`'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; +@@ -14874,12 +14875,18 @@ + options = undefined; + } + string = toString(string); +- options = assignInWith({}, options, settings, customDefaultsAssignIn); ++ options = assignWith({}, options, settings, customDefaultsAssignIn); + +- var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), ++ var imports = assignWith({}, options.imports, settings.imports, customDefaultsAssignIn), + importsKeys = keys(imports), + importsValues = baseValues(imports, importsKeys); + ++ arrayEach(importsKeys, function(key) { ++ if (reForbiddenIdentifierChars.test(key)) { ++ throw new Error(INVALID_TEMPL_IMPORTS_ERROR_TEXT); ++ } ++ }); ++ + var isEscaping, + isEvaluating, + index = 0, +--- a/test/test.js ++++ b/test/test.js +@@ -22692,6 +22692,52 @@ + + assert.deepEqual(actual, ['one', '"two"', 'three']); + }); ++ ++ // Related to https://github.com/lodash/lodash/security/advisories/GHSA-r5fr-rjxr-66jc ++ QUnit.test('should not execute code via malicious imports key names', function(assert) { ++ assert.expect(2); ++ ++ // Default-parameter injection via imports key ++ var executed = false; ++ var key = 'a = (global.templateTest1 = true, 1)'; ++ var imports = {}; ++ imports[key] = undefined; ++ ++ try { _.template('hello', { 'imports': imports }); } catch (e) {} ++ executed = root.templateTest1 === true; ++ delete root.templateTest1; ++ ++ assert.strictEqual(executed, false, 'should not execute default-parameter expression in imports key'); ++ ++ // Same without spaces ++ var executed2 = false; ++ var key2 = 'a=(global.templateTest2=true,1)'; ++ var imports2 = {}; ++ imports2[key2] = undefined; ++ ++ try { _.template('hello', { 'imports': imports2 }); } catch (e) {} ++ executed2 = root.templateTest2 === true; ++ delete root.templateTest2; ++ ++ assert.strictEqual(executed2, false, 'should not execute compact default-parameter expression in imports key'); ++ }); ++ ++ // Related to https://github.com/lodash/lodash/security/advisories/GHSA-r5fr-rjxr-66jc ++ QUnit.test('should not enumerate inherited keys from imports sources', function(assert) { ++ assert.expect(1); ++ ++ // Simulate prototype pollution: inherited key with code injection ++ var executed = false; ++ var payload = 'a = (global.templateTest3 = true, 1)'; ++ var polluted = Object.create({ [payload]: undefined }); ++ polluted._ = _; ++ ++ try { _.template('hello', { 'imports': polluted }); } catch (e) {} ++ executed = root.templateTest3 === true; ++ delete root.templateTest3; ++ ++ assert.strictEqual(executed, false, 'should not execute code from inherited imports keys'); ++ }); + }()); + + /*--------------------------------------------------------------------------*/ diff -Nru node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/series node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/series --- node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/series 2022-05-23 21:18:19.000000000 +0530 +++ node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/patches/series 2026-07-05 02:41:49.000000000 +0530 @@ -2,3 +2,7 @@ webpack-4-compat.patch fp_no_min.patch fix-for-webpack5.patch +CVE-2025-13465.patch +CVE-2026-2950.patch +CVE-2026-4800.patch +CVE-2026-4800-modular-template-deps.patch diff -Nru node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/source/options node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/source/options --- node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/source/options 1970-01-01 05:30:00.000000000 +0530 +++ node-lodash-4.17.21+dfsg+~cs8.31.198.20210220/debian/source/options 2026-07-05 02:41:49.000000000 +0530 @@ -0,0 +1 @@ +extend-diff-ignore = "(^|/)(types-lodash(-[^/]+)?/(LICENSE|README\.md))$"