Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: angular...@packages.debian.org
Control: affects -1 + src:angular.js
User: release.debian....@packages.debian.org
Usertags: pu

[ Reason ]
Fix all CVEs except CVE-2022-25869 that need iexplore and is no-dsa

[ Impact ]
CVEs are still opened

[ Tests ]
autopkgtest where added for redos. Manual test for XSS. regression testsuite

[ Risks ]
Low

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

[ Changes ]
+
+  * Team upload
+  * Move to js team umbrella
+  * Fix CVE-2022-25844 (Closes: #1014779)
+    A Regular Expression Denial of Service vulnerability (ReDoS)
+    was found by providing a custom locale rule that makes
+    it possible to assign the parameter in posPre: ' '.repeat()
+    of NUMBER_FORMATS.PATTERNS[1].posPre with a very high value
+  * Fix CVE-2023-26116 (Closes: #1036694)
+    A Regular Expression Denial of Service (ReDoS) was found
+    via the angular.copy() utility function due to the usage
+    of an insecure regular expression.
+  * Fix CVE-2023-26116 (Closes: #1036694)
+    A Regular Expression Denial of Service (ReDoS) was found
+    via the angular.copy() utility function due to the usage
+    of an insecure regular expression.
+  * Fix CVE-2023-26117:
+    A Regular Expression Denial of Service (ReDoS) was found
+    via the $resource service due to the usage of an insecure
+    regular expression.
+  * Fix CVE-2023-26118:
+    A Regular Expression Denial of Service (ReDoS) was found
+    via the <input type="url"> element due to the usage of an
+    insecure regular expression in the input[url] functionality.
+    Exploiting this vulnerability is possible by a large
+    carefully-crafted input, which can result in catastrophic
+    backtracking.
+  * Fix CVE-2024-8372: (Closes: #1088804)
+    Improper sanitization of the value of the 'srcset'
+    attribute in AngularJS allows attackers to bypass
+    common image source restrictions, which can also
+    lead to a form of Content Spoofing
+  * Fix CVE-2024-8373: (Closes: #1088805)
+    Improper sanitization of the value of the [srcset]
+    attribute in <source> HTML elements in AngularJS allows
+    attackers to bypass common image source restrictions,
+    which can also lead to a form of Content Spoofing
+  * Fix CVE-2024-21490:
+    A regular expression used to split
+    the value of the ng-srcset directive is vulnerable to
+    super-linear runtime due to backtracking. With large
+    carefully-crafted input, this can result in catastrophic
+    backtracking and cause a denial of service.
+  * Fix CVE-2025-0716: (Closes: #1104485)
+    Improper sanitization of the value of the 'href'
+    and 'xlink:href' attributes in '<image>' SVG elements
+    in AngularJS allows attackers to bypass common image
+    source restrictions. This can lead to a form of
+    Content Spoofing .
+  * Fix CVE-2025-2336:
+    An improper sanitization vulnerability has been identified
+    in ngSanitize module, which allows attackers to bypass
+    common image source restrictions normally
+    applied to image elements. This bypass can further lead to a form of
+    Content Spoofing. Similarly, the application's performance and behavior
+    could be negatively affected by using too large or slow-to-load images.
+

[ Other info ]
Review by kapouer and kanishiro and LTS team
diff -Nru angular.js-1.8.3/debian/changelog angular.js-1.8.3/debian/changelog
--- angular.js-1.8.3/debian/changelog	2023-02-12 07:45:48.000000000 +0100
+++ angular.js-1.8.3/debian/changelog	2025-05-11 23:40:38.000000000 +0200
@@ -1,3 +1,60 @@
+angular.js (1.8.3-1+deb12u1) bookworm; urgency=medium
+
+  * Team upload
+  * Move to js team umbrella
+  * Fix CVE-2022-25844 (Closes: #1014779)
+    A Regular Expression Denial of Service vulnerability (ReDoS)
+    was found by providing a custom locale rule that makes
+    it possible to assign the parameter in posPre: ' '.repeat()
+    of NUMBER_FORMATS.PATTERNS[1].posPre with a very high value
+  * Fix CVE-2023-26116 (Closes: #1036694)
+    A Regular Expression Denial of Service (ReDoS) was found
+    via the angular.copy() utility function due to the usage
+    of an insecure regular expression.
+  * Fix CVE-2023-26117:
+    A Regular Expression Denial of Service (ReDoS) was found
+    via the $resource service due to the usage of an insecure
+    regular expression.
+  * Fix CVE-2023-26118:
+    A Regular Expression Denial of Service (ReDoS) was found
+    via the <input type="url"> element due to the usage of an
+    insecure regular expression in the input[url] functionality.
+    Exploiting this vulnerability is possible by a large
+    carefully-crafted input, which can result in catastrophic
+    backtracking.
+  * Fix CVE-2024-8372: (Closes: #1088804)
+    Improper sanitization of the value of the 'srcset'
+    attribute in AngularJS allows attackers to bypass
+    common image source restrictions, which can also
+    lead to a form of Content Spoofing
+  * Fix CVE-2024-8373: (Closes: #1088805)
+    Improper sanitization of the value of the [srcset]
+    attribute in <source> HTML elements in AngularJS allows
+    attackers to bypass common image source restrictions,
+    which can also lead to a form of Content Spoofing
+  * Fix CVE-2024-21490:
+    A regular expression used to split
+    the value of the ng-srcset directive is vulnerable to
+    super-linear runtime due to backtracking. With large
+    carefully-crafted input, this can result in catastrophic
+    backtracking and cause a denial of service.
+  * Fix CVE-2025-0716: (Closes: #1104485)
+    Improper sanitization of the value of the 'href'
+    and 'xlink:href' attributes in '<image>' SVG elements
+    in AngularJS allows attackers to bypass common image
+    source restrictions. This can lead to a form of
+    Content Spoofing .
+  * Fix CVE-2025-2336:
+    An improper sanitization vulnerability has been identified
+    in ngSanitize module, which allows attackers to bypass
+    common image source restrictions normally
+    applied to image elements. This bypass can further lead to a form of
+    Content Spoofing. Similarly, the application's performance and behavior
+    could be negatively affected by using too large or slow-to-load images.
+
+
+ -- Bastien Roucariès <ro...@debian.org>  Sun, 11 May 2025 23:40:38 +0200
+
 angular.js (1.8.3-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru angular.js-1.8.3/debian/control angular.js-1.8.3/debian/control
--- angular.js-1.8.3/debian/control	2021-01-12 18:12:31.000000000 +0100
+++ angular.js-1.8.3/debian/control	2025-05-11 23:40:38.000000000 +0200
@@ -1,11 +1,14 @@
 Source: angular.js
 Section: javascript
 Priority: optional
-Maintainer: Laszlo Boszormenyi (GCS) <g...@debian.org>
+Maintainer: Debian Javascript Maintainers <pkg-javascript-de...@lists.alioth.debian.org>
+Uploaders: Laszlo Boszormenyi (GCS) <g...@debian.org>
 Build-Depends: debhelper-compat (= 13), gawk, node-smash (>= 0.0.15-2), uglifyjs, libjs-jquery
 Standards-Version: 4.5.1
 Homepage: https://angularjs.org/
 Rules-Requires-Root: no
+Vcs-Browser: https://salsa.debian.org/js-team/angular.js
+Vcs-Git: https://salsa.debian.org/js-team/angular.js.git
 
 Package: libjs-angularjs
 Architecture: all
diff -Nru angular.js-1.8.3/debian/patches/CVE-2022-25844.patch angular.js-1.8.3/debian/patches/CVE-2022-25844.patch
--- angular.js-1.8.3/debian/patches/CVE-2022-25844.patch	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/CVE-2022-25844.patch	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,50 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <ro...@debian.org>
+Date: Mon, 12 May 2025 00:34:07 +0200
+Subject: CVE-2022-25844
+
+Avoid a redos by avoiding regex
+
+bug: https://snyk.io/vuln/SNYK-JS-ANGULAR-2772735
+bug-debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1014779
+origin: part, https://github.com/PebblePad/angular.js/commit/ecfd8d3389d1ef813735febf6bf48ff5d970bc51
+author: Alister Stevens <alis...@pebblepad.co.uk>
+---
+ src/ng/filter/filters.js | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/src/ng/filter/filters.js b/src/ng/filter/filters.js
+index 482b318..d5106e4 100644
+--- a/src/ng/filter/filters.js
++++ b/src/ng/filter/filters.js
+@@ -68,14 +68,24 @@ function currencyFilter($locale) {
+       fractionSize = formats.PATTERNS[1].maxFrac;
+     }
+ 
+-    // If the currency symbol is empty, trim whitespace around the symbol
+-    var currencySymbolRe = !currencySymbol ? /\s*\u00A4\s*/g : /\u00A4/g;
+-
+     // if null or undefined pass it through
+-    return (amount == null)
+-        ? amount
+-        : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).
+-            replace(currencySymbolRe, currencySymbol);
++    if (amount === null || amount === undefined) {
++      return amount;
++    }
++
++    const formattedNumber = formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize);
++    // Validate if currency symbol whitespace trimming is required by checking for the currency symbol first. Fixes potential ReDoS vulnerability - https://www.cve.org/CVERecord?id=CVE-2022-25844
++    if(!formattedNumber.includes("\u00A4")) return formattedNumber;
++    if(currencySymbol) return formattedNumber.replace(/\u00A4/g,currencySymbol);
++    /* here we know we have u00A4 so at least 2 splitted part and currency symbol is empty*/
++    let splitted = formattedNumber.split("\u00A4");
++    const splittedend = splitted.length - 1;
++    splitted[0] = splitted[0].trimEnd();
++    splitted[splittedend] = splitted[splittedend].trimStart();
++    if(splittedend > 1) {
++       for(let i=1;i < splittedend; i++) splitted[i] = splitted[i].trim();
++    }
++    return splitted.join('');
+   };
+ }
+ 
diff -Nru angular.js-1.8.3/debian/patches/CVE-2023-26116.patch angular.js-1.8.3/debian/patches/CVE-2023-26116.patch
--- angular.js-1.8.3/debian/patches/CVE-2023-26116.patch	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/CVE-2023-26116.patch	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,25 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <ro...@debian.org>
+Date: Mon, 12 May 2025 00:58:29 +0200
+Subject: CVE-2023-26116
+
+Fix the redos by using regex.flags available since 2020 for all browser
+
+bug: https://security.snyk.io/vuln/SNYK-JS-ANGULAR-3373044
+origin: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1036694
+---
+ src/Angular.js | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/Angular.js b/src/Angular.js
+index 9b11090..79f4a95 100644
+--- a/src/Angular.js
++++ b/src/Angular.js
+@@ -999,7 +999,7 @@ function copy(source, destination, maxDepth) {
+         return new source.constructor(source.valueOf());
+ 
+       case '[object RegExp]':
+-        var re = new RegExp(source.source, source.toString().match(/[^/]*$/)[0]);
++        var re = new RegExp(source.source, source.flags);
+         re.lastIndex = source.lastIndex;
+         return re;
+ 
diff -Nru angular.js-1.8.3/debian/patches/CVE-2023-26117.patch angular.js-1.8.3/debian/patches/CVE-2023-26117.patch
--- angular.js-1.8.3/debian/patches/CVE-2023-26117.patch	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/CVE-2023-26117.patch	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,30 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <ro...@debian.org>
+Date: Mon, 12 May 2025 01:19:39 +0200
+Subject: CVE-2023-26117
+
+Fix by linear replace a redos
+
+bug-poc: https://stackblitz.com/edit/angularjs-vulnerability-resource-trailing-slashes-redos?file=index.js
+bug: https://security.snyk.io/vuln/SNYK-JS-ANGULAR-3373045
+bug-debian: https://bugs.debian.org/1036694
+---
+ src/ngResource/resource.js | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/ngResource/resource.js b/src/ngResource/resource.js
+index 11bb45b..3249e3e 100644
+--- a/src/ngResource/resource.js
++++ b/src/ngResource/resource.js
+@@ -651,7 +651,11 @@ angular.module('ngResource', ['ng']).
+ 
+           // strip trailing slashes and set the url (unless this behavior is specifically disabled)
+           if (self.defaults.stripTrailingSlashes) {
+-            url = url.replace(/\/+$/, '') || '/';
++            var i = url.length - 1;
++            while (i >= 0 && url[i] == ('/')) {
++               i--;
++            }
++            url = url.slice(0,i + 1) || '/';
+           }
+ 
+           // Collapse `/.` if found in the last URL path segment before the query.
diff -Nru angular.js-1.8.3/debian/patches/CVE-2023-26118.patch angular.js-1.8.3/debian/patches/CVE-2023-26118.patch
--- angular.js-1.8.3/debian/patches/CVE-2023-26118.patch	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/CVE-2023-26118.patch	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,40 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <ro...@debian.org>
+Date: Mon, 12 May 2025 22:31:48 +0200
+Subject: CVE-2023-26118
+
+Regular Expression Denial of Service (ReDoS) via the <input type="url"> element due to the
+usage of an insecure regular expression in the input[url] functionality.
+
+Exploiting this vulnerability is possible by a large carefully-crafted input, which can result in catastrophic backtracking.
+
+origin: backport, https://github.com/angular/angular/blob/3c9b8d9de5978dad99d49aa0107a70eddc4d1968/packages/misc/angular-in-memory-web-api/src/interfaces.ts#L135
+bug: https://security.snyk.io/vuln/SNYK-JS-ANGULAR-3373046
+bug-debian: https://bugs.debian.org/1036694
+---
+ src/ng/directive/input.js | 13 +------------
+ 1 file changed, 1 insertion(+), 12 deletions(-)
+
+diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js
+index 7dfbf16..90f321b 100644
+--- a/src/ng/directive/input.js
++++ b/src/ng/directive/input.js
+@@ -11,18 +11,7 @@
+ // Regex code was initially obtained from SO prior to modification: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
+ var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/;
+ // See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987)
+-// Note: We are being more lenient, because browsers are too.
+-//   1. Scheme
+-//   2. Slashes
+-//   3. Username
+-//   4. Password
+-//   5. Hostname
+-//   6. Port
+-//   7. Path
+-//   8. Query
+-//   9. Fragment
+-//                 1111111111111111 222   333333    44444        55555555555555555555555     666     77777777     8888888     999
+-var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i;
++var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^/:@][^:@]*(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i
+ // eslint-disable-next-line max-len
+ var EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;
+ var NUMBER_REGEXP = /^\s*(-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
diff -Nru angular.js-1.8.3/debian/patches/CVE-2024-21490.patch angular.js-1.8.3/debian/patches/CVE-2024-21490.patch
--- angular.js-1.8.3/debian/patches/CVE-2024-21490.patch	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/CVE-2024-21490.patch	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,75 @@
+From: Chris Rowe <ch...@pebblepad.co.uk>
+Date: Tue, 17 Sep 2024 16:49:06 +0100
+Subject: CVE-2024-21490 and CVE-2024-8372
+
+Fix ReDoS vulnerability with ng-srcset
+
+Fix also CVE-2024-8372 by sanitizing
+
+origin: backport, https://github.com/PebblePad/angular.js/commit/2111de19f71fa70ed8aa0a0797612718a6f6e867
+bug: https://codepen.io/herodevs/full/xxoQRNL/0072e627abe03e9cda373bc75b4c1017
+bug-debian: https://bugs.debian.org/1088804
+bug-cve: https://www.cve.org/CVERecord?id=CVE-2024-21490
+---
+ src/ng/compile.js | 46 ++++++++--------------------------------------
+ 1 file changed, 8 insertions(+), 38 deletions(-)
+
+diff --git a/src/ng/compile.js b/src/ng/compile.js
+index e48b5a9..b90318f 100644
+--- a/src/ng/compile.js
++++ b/src/ng/compile.js
+@@ -2086,46 +2086,16 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
+         throw $compileMinErr('srcset', 'Can\'t pass trusted values to `{0}`: "{1}"', invokeType, value.toString());
+       }
+ 
+-      // Such values are a bit too complex to handle automatically inside $sce.
+-      // Instead, we sanitize each of the URIs individually, which works, even dynamically.
+-
+-      // It's not possible to work around this using `$sce.trustAsMediaUrl`.
+-      // If you want to programmatically set explicitly trusted unsafe URLs, you should use
+-      // `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the
+-      // `ng-bind-html` directive.
+-
+-      var result = '';
+-
+-      // first check if there are spaces because it's not the same pattern
+-      var trimmedSrcset = trim(value);
+-      //                (   999x   ,|   999w   ,|   ,|,   )
+-      var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
+-      var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
+-
+-      // split srcset into tuple of uri and descriptor except for the last item
+-      var rawUris = trimmedSrcset.split(pattern);
+-
+-      // for each tuples
+-      var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
+-      for (var i = 0; i < nbrUrisWith2parts; i++) {
+-        var innerIdx = i * 2;
+-        // sanitize the uri
+-        result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx]));
+-        // add the descriptor
+-        result += ' ' + trim(rawUris[innerIdx + 1]);
++      var srcSetValues = value.split(',')
++      var sanitisedSrcSet = [];
++      for (const srcSetValue of srcSetValues) {
++        const wellTrimmedSrcSetValue = srcSetValue.trim().replace(/\s{2,}/, ' ');
++        const srcSplit = wellTrimmedSrcSetValue.split(' ');
++        const uri = $sce.getTrustedMediaUrl(srcSplit[0]);
++        sanitisedSrcSet.push(`${uri}${srcSplit[1] !== undefined ? " " + srcSplit[1] : ""}`)
+       }
+ 
+-      // split the last item into uri and descriptor
+-      var lastTuple = trim(rawUris[i * 2]).split(/\s/);
+-
+-      // sanitize the last uri
+-      result += $sce.getTrustedMediaUrl(trim(lastTuple[0]));
+-
+-      // and add the last descriptor if any
+-      if (lastTuple.length === 2) {
+-        result += (' ' + trim(lastTuple[1]));
+-      }
+-      return result;
++      return sanitisedSrcSet.join(',');
+     }
+ 
+ 
diff -Nru angular.js-1.8.3/debian/patches/CVE-2024-8373.patch angular.js-1.8.3/debian/patches/CVE-2024-8373.patch
--- angular.js-1.8.3/debian/patches/CVE-2024-8373.patch	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/CVE-2024-8373.patch	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,23 @@
+From: Alister Stevens <alis...@pebblepad.co.uk>
+Date: Wed, 18 Sep 2024 16:10:46 +0100
+Subject: CVE-2024-8373
+
+origin: backport, https://github.com/PebblePad/angular.js/commit/7cb36590cdfb23fc2106868b21eb7a78311eb36d
+bug-cve: ttps://www.cve.org/CVERecord?id=CVE-2024-8373
+---
+ src/ng/compile.js | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/ng/compile.js b/src/ng/compile.js
+index b90318f..8e7cf98 100644
+--- a/src/ng/compile.js
++++ b/src/ng/compile.js
+@@ -2235,7 +2235,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
+         nodeName = nodeName_(this.$$element);
+ 
+         // Sanitize img[srcset] values.
+-        if (nodeName === 'img' && key === 'srcset') {
++        if ((nodeName === 'img' || nodeName === 'source') && key === 'srcset') {
+           this[key] = value = sanitizeSrcset(value, '$set(\'srcset\', value)');
+         }
+ 
diff -Nru angular.js-1.8.3/debian/patches/CVE-2025-0716.patch angular.js-1.8.3/debian/patches/CVE-2025-0716.patch
--- angular.js-1.8.3/debian/patches/CVE-2025-0716.patch	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/CVE-2025-0716.patch	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,30 @@
+From: Alister Stevens <alis...@pebblepad.co.uk>
+Date: Tue, 6 May 2025 13:40:27 +0100
+Subject: Fix improper sanitisation of href and xlink:href on SVG image
+ elements
+
+Fix CVE-2025-0716
+
+origin: backport, https://github.com/PebblePad/angular.js/commit/71513129efd044c09e52d47455d73c62ff3287d8
+bug: https://www.herodevs.com/vulnerability-directory/cve-2025-0716?angularjs-nes
+bug-poc: https://codepen.io/herodevs/pen/qEWQmpd/a86a0d29310e12c7a3756768e6c7b915
+---
+ src/ng/compile.js | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/ng/compile.js b/src/ng/compile.js
+index 8e7cf98..c525895 100644
+--- a/src/ng/compile.js
++++ b/src/ng/compile.js
+@@ -3807,6 +3807,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
+           (nodeName === 'link' && attrNormalizedName === 'href')
+       ) {
+         return $sce.RESOURCE_URL;
++      } else if (
++          // SVG image href can be abused (content spoofing)
++          (nodeName === "image") && (attrNormalizedName === 'href' || attrNormalizedName === 'ngHref')
++      ) {
++        return $sce.MEDIA_URL;
+       } else if (nodeName === 'a' && (attrNormalizedName === 'href' ||
+                                  attrNormalizedName === 'ngHref')) {
+         return $sce.URL;
diff -Nru angular.js-1.8.3/debian/patches/CVE-2025-2336.patch angular.js-1.8.3/debian/patches/CVE-2025-2336.patch
--- angular.js-1.8.3/debian/patches/CVE-2025-2336.patch	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/CVE-2025-2336.patch	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,47 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <ro...@debian.org>
+Date: Sat, 7 Jun 2025 22:22:12 +0200
+Subject: CVE-2025-2336
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+An improper sanitization vulnerability has been identified in AngularJS' ngSanitize module,
+which allows attackers to bypass common image source restrictions normally
+applied to image elements. This bypass can further lead to a form of
+Content Spoofing. Similarly, the application's performance and behavior
+could be negatively affected by using too large or slow-to-load images.
+
+The $sanitize service, which is provided by the angular-sanitize package,
+is used for sanitizing HTML strings by stripping all potentially dangerous tokens.
+As part of the sanitization, it checks the URLs of images to ensure they
+abide by the defined image source rules. This allows improving the security
+of an application by setting restrictions on the sources of images
+that can be shown. For example, only allowing images from a specific domain.
+
+‍However, due to a bug in the $sanitize service, SVG <image> elements
+are not correctly detected as images, even when SVG support is enabled.
+As a result, the image source restrictions are not applied to the images
+that can be shown. This allows bypassing the image source restrictions configured
+in the application, which can also lead to a form of Content Spoofing.
+Similarly, the application's performance and behavior can be negatively affected
+by using too large or slow-to-load images.
+
+bug: https://www.herodevs.com/vulnerability-directory/cve-2025-2336
+bug-PoC: https://codepen.io/herodevs/pen/bNGYaXx/412a3a4218387479898912f60c269c6c
+---
+ src/ngSanitize/sanitize.js | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/ngSanitize/sanitize.js b/src/ngSanitize/sanitize.js
+index 34e0e09..64ce508 100644
+--- a/src/ngSanitize/sanitize.js
++++ b/src/ngSanitize/sanitize.js
+@@ -598,7 +598,7 @@ function $SanitizeProvider() {
+           out(tag);
+           forEach(attrs, function(value, key) {
+             var lkey = lowercase(key);
+-            var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
++            var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background') || (tag === 'image' && (lkey === 'href' || lkey === 'xlink:href'));
+             if (validAttrs[lkey] === true &&
+               (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
+               out(' ');
diff -Nru angular.js-1.8.3/debian/patches/series angular.js-1.8.3/debian/patches/series
--- angular.js-1.8.3/debian/patches/series	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/patches/series	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,8 @@
+CVE-2022-25844.patch
+CVE-2023-26116.patch
+CVE-2023-26117.patch
+CVE-2023-26118.patch
+CVE-2024-21490.patch
+CVE-2024-8373.patch
+CVE-2025-0716.patch
+CVE-2025-2336.patch
diff -Nru angular.js-1.8.3/debian/salsa-ci.yml angular.js-1.8.3/debian/salsa-ci.yml
--- angular.js-1.8.3/debian/salsa-ci.yml	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/salsa-ci.yml	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,6 @@
+include:
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
+
+variables:
+  RELEASE: 'sid'
+  SALSA_CI_COMPONENTS: 'main contrib non-free'
diff -Nru angular.js-1.8.3/debian/tests/control angular.js-1.8.3/debian/tests/control
--- angular.js-1.8.3/debian/tests/control	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/tests/control	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,14 @@
+Test-Command: timeout 60 /usr/bin/env node debian/tests/CVE-2022-25844-PoC.js
+Depends: libjs-angularjs, nodejs, node-jsdom
+
+Test-Command: timeout 60 /usr/bin/env node debian/tests/CVE-2023-26116-PoC.js
+Depends: libjs-angularjs, nodejs, node-jsdom
+
+Test-Command: timeout 60 /usr/bin/env node debian/tests/CVE-2023-26117-PoC.js
+Depends: libjs-angularjs, nodejs, node-jsdom
+
+Test-Command: timeout 60 /usr/bin/env node debian/tests/CVE-2023-26118-PoC.js
+Depends: libjs-angularjs, nodejs, node-jsdom
+
+Test-Command: timeout 30 /usr/bin/env node debian/tests/CVE-2024-21490-PoC.js
+Depends: libjs-angularjs, nodejs, node-jsdom
diff -Nru angular.js-1.8.3/debian/tests/CVE-2022-25844-PoC.js angular.js-1.8.3/debian/tests/CVE-2022-25844-PoC.js
--- angular.js-1.8.3/debian/tests/CVE-2022-25844-PoC.js	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/tests/CVE-2022-25844-PoC.js	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,52 @@
+const { JSDOM, VirtualConsole } = require('jsdom');
+const fs = require('fs');
+
+const angularJS = fs.readFileSync('/usr/share/javascript/angular.js/angular.min.js', 'utf-8');
+
+const virtualConsole = new VirtualConsole();
+virtualConsole.sendTo(console);
+
+const html = `
+<!DOCTYPE html><html><head><script>${angularJS}</script>
+<script>
+  angular.module('app', [])
+    .controller('AppCtrl', function($locale, $filter) {
+      const ctrl = this;
+
+      // Malicious input to trigger potential ReDoS
+      const malicious = ' '.repeat(1e6);
+
+      console.log('Applying potentially malicious pattern...');
+      $locale.NUMBER_FORMATS.PATTERNS[1].posPre = malicious;
+      $locale.NUMBER_FORMATS.CURRENCY_SYM = '';
+
+      const start = Date.now();
+      try {
+        const formatted = $filter('currency')(100);
+        const duration = Date.now() - start;
+        console.log('Duration:', duration, 'ms');
+
+        if (duration > 2000) {
+          process.exit(2);
+        } else {
+          process.exit(0);
+        }
+      } catch (err) {
+        process.exit(1);
+      }
+    });
+</script></head>
+<body ng-app="app" ng-controller="AppCtrl as ctrl"></body></html>`;
+
+const dom = new JSDOM(html, {
+  runScripts: 'dangerously',
+  resources: 'usable',
+  virtualConsole,
+  pretendToBeVisual: true
+});
+dom.window.process = process;
+
+dom.window.document.addEventListener("DOMContentLoaded", () => {
+  const angular = dom.window.angular;
+  angular.bootstrap(dom.window.document, ['app']);
+});
diff -Nru angular.js-1.8.3/debian/tests/CVE-2023-26116-PoC.js angular.js-1.8.3/debian/tests/CVE-2023-26116-PoC.js
--- angular.js-1.8.3/debian/tests/CVE-2023-26116-PoC.js	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/tests/CVE-2023-26116-PoC.js	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,86 @@
+#!/usr/bin/env node
+
+const { JSDOM, VirtualConsole } = require("jsdom");
+const fs = require("fs");
+
+const angularPath = "/usr/share/javascript/angular.js/angular.min.js";
+const angularResource = "/usr/share/javascript/angular.js/angular-resource.min.js";
+const angularMocks = "/usr/share/javascript/angular.js/angular-mocks.js";
+
+const angularJS          = fs.readFileSync(angularPath, "utf-8");
+const angularResourceJS  = fs.readFileSync(angularResource, "utf-8");
+const angularMocksJS     = fs.readFileSync(angularMocks, "utf-8");
+
+const html = `
+<!DOCTYPE html>
+<html>
+<head>
+  <script>${angularJS}</script>
+  <script>${angularResourceJS}</script>
+  <script>${angularMocksJS}</script>
+
+  <script>
+  class AppCtrl {
+    regexPattern = null;
+    duration = '(N/A)';
+
+    constructor() {
+      this.setRegexPatternWithCharsPowerOf2Exponent(17);
+      setTimeout(() => {
+           console.log("[E] Timeout");
+           windows.process.exit(3);
+         }, 40 * 1000)
+      this.runTest();
+    }
+
+    setRegexPatternWithCharsPowerOf2Exponent(exponent) {
+      this.regexPattern = 'x'.repeat(2 ** exponent);
+    }
+
+    runTest() {
+      // Escape spacial regular expression characters.
+      const pattern = this.regexPattern.replace(/[-.?*+^$|\\\/(){}[\]]/g, '\\$&');
+      const regex = new RegExp(pattern);
+
+      const start = Date.now();
+      angular.copy(regex);
+      const end = Date.now();
+
+      this.duration = ((end - start) / 1000).toFixed(2);
+      console.log(\`Query setup time: \${this.duration} sec\`);
+      if (this.duration > 3) {
+        console.log("[E] It took too long!");
+        window.process.exit(2);
+      } else {
+        window.process.exit(0);
+      }
+    }
+  }
+
+  angular
+      .module('app', [])
+      .controller('AppCtrl', AppCtrl);
+  </script>
+</head>
+<body ng-app="app" ng-controller="AppCtrl as ctrl">
+</body>
+</html>
+`;
+
+const virtualConsole = new VirtualConsole();
+virtualConsole.sendTo(console);
+
+const dom = new JSDOM(html, {
+  runScripts: "dangerously",
+  resources: "usable",
+  virtualConsole
+});
+dom.window.process = process;
+
+dom.window.document.addEventListener("DOMContentLoaded", () => {
+  const angular = dom.window.angular;
+  angular.element(dom.window.document).ready(() => {
+    angular.bootstrap(dom.window.document, ['app']);
+  });
+});
+
diff -Nru angular.js-1.8.3/debian/tests/CVE-2023-26117-PoC.js angular.js-1.8.3/debian/tests/CVE-2023-26117-PoC.js
--- angular.js-1.8.3/debian/tests/CVE-2023-26117-PoC.js	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/tests/CVE-2023-26117-PoC.js	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,90 @@
+#!/usr/bin/env node
+
+const { JSDOM, VirtualConsole } = require("jsdom");
+const fs = require("fs");
+
+const angularPath = "/usr/share/javascript/angular.js/angular.min.js";
+const angularResource = "/usr/share/javascript/angular.js/angular-resource.min.js";
+const angularMocks = "/usr/share/javascript/angular.js/angular-mocks.js";
+
+const angularJS          = fs.readFileSync(angularPath, "utf-8");
+const angularResourceJS  = fs.readFileSync(angularResource, "utf-8");
+const angularMocksJS     = fs.readFileSync(angularMocks, "utf-8");
+
+const html = `
+<!DOCTYPE html>
+<html>
+<head>
+  <script>${angularJS}</script>
+  <script>${angularResourceJS}</script>
+  <script>${angularMocksJS}</script>
+
+  <script>
+    class AppCtrl {
+      constructor($resource) {
+        this.$resource = $resource;
+        this.urlSuffix = null;
+        this.duration = '(N/A)';
+        this.setUrlSuffixWithSlashesPowerOf2Exponent(17); // 131,078 slashes
+        this.runTest();
+      }
+
+      setUrlSuffixWithSlashesPowerOf2Exponent(exp) {
+        this.urlSuffix = 'foo' + '/'.repeat(2 ** exp) + 'bar';
+      }
+
+      runTest() {
+        const api = this.$resource(
+          '/api/test/' + this.urlSuffix,
+          {},
+          { query: { method: 'GET', isArray: false } }
+        );
+
+        const start = Date.now();
+        const res = api.query();
+        const end = Date.now();
+
+        this.duration = ((end - start) / 1000).toFixed(2);
+        console.log(\`Query setup time: \${this.duration} sec\`);
+	if (this.duration > 20) {
+	  console.log("[E] It took too long!");
+	  window.process.exit(2);
+	} else {
+	  window.process.exit(0);
+	}
+
+        // Clean up
+        res.$cancelRequest();
+      }
+    }
+
+    angular.module('app', ['ngResource', 'ngMockE2E'])
+      .controller('AppCtrl', ['$resource', AppCtrl])
+      .run(['$httpBackend', function($httpBackend) {
+        $httpBackend.whenGET(/^\\/api\\/test\\/.*$/)
+                    .respond(200, { ok: true });
+      }]);
+  </script>
+</head>
+<body ng-app="app" ng-controller="AppCtrl as ctrl">
+</body>
+</html>
+`;
+
+const virtualConsole = new VirtualConsole();
+virtualConsole.sendTo(console);
+
+const dom = new JSDOM(html, {
+  runScripts: "dangerously",
+  resources: "usable",
+  virtualConsole
+});
+dom.window.process = process;
+
+dom.window.document.addEventListener("DOMContentLoaded", () => {
+  const angular = dom.window.angular;
+  angular.element(dom.window.document).ready(() => {
+    angular.bootstrap(dom.window.document, ['app']);
+  });
+});
+
diff -Nru angular.js-1.8.3/debian/tests/CVE-2023-26118-PoC.js angular.js-1.8.3/debian/tests/CVE-2023-26118-PoC.js
--- angular.js-1.8.3/debian/tests/CVE-2023-26118-PoC.js	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/tests/CVE-2023-26118-PoC.js	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,96 @@
+#!/usr/bin/env node
+
+const { JSDOM, VirtualConsole } = require("jsdom");
+const fs = require("fs");
+
+const angularPath = "/usr/share/javascript/angular.js/angular.min.js";
+const angularResource = "/usr/share/javascript/angular.js/angular-resource.min.js";
+const angularMocks = "/usr/share/javascript/angular.js/angular-mocks.js";
+
+const angularJS          = fs.readFileSync(angularPath, "utf-8");
+const angularResourceJS  = fs.readFileSync(angularResource, "utf-8");
+const angularMocksJS     = fs.readFileSync(angularMocks, "utf-8");
+
+const html = `
+<!DOCTYPE html>
+<html>
+<head>
+  <script>${angularJS}</script>
+  <script>${angularResourceJS}</script>
+  <script>${angularMocksJS}</script>
+
+  <script>
+    // Define controllers.
+    class AppCtrl {
+      url = null;
+      urlInput = null;
+      urlInputController = null;
+      urlInputValidators = null;
+      duration = '(N/A)';
+
+      constructor() {
+	this.setUrlWithSlashesPowerOf2Exponent(20);
+      }
+
+      $postLink() {
+	// Remove the default validators (which include the URL validator) to prevent
+	// the browser's freezing during entering a value and run validation on demand.
+	this.urlInputController = this.urlInput.controller('ngModel');
+      }
+
+      setUrlWithSlashesPowerOf2Exponent(exponent) {
+	this.url = 'scheme:'+('/'.repeat(2 ** exponent));
+      }
+
+      validateUrl() {
+	  // Temporarily restore the default validators (which include the URL validator)
+	  // and run validation on demand (while measuring the time it takes).
+	  const start = Date.now();
+	  this.urlInputController.$validate();
+	  const end = Date.now();
+
+	  //this.urlInputController.$validators = {};
+	  this.duration = ((end - start) / 1000).toFixed(2);
+          console.log(\`Query setup time: \${this.duration} sec\`);
+          if (this.duration > 20) {
+            console.log("[E] It took too long!");
+            window.process.exit(2);
+          } else {
+            window.process.exit(0);
+          }
+	}
+    }
+
+    // Define and configure the app.
+    const app = angular
+	.module('app', [])
+	.controller('AppCtrl', AppCtrl);
+    setTimeout(() => {
+       angular.element(document.body).scope().$ctrl.setUrlWithSlashesPowerOf2Exponent(20);
+       angular.element(document.body).scope().$ctrl.validateUrl();
+     } , 200);
+  </script>
+</head>
+<body ng-app="app" ng-controller="AppCtrl as $ctrl">
+<input type="url" ng-ref="$ctrl.urlInput" ng-model="$ctrl.url" />
+</body>
+</html>
+`;
+
+const virtualConsole = new VirtualConsole();
+virtualConsole.sendTo(console);
+
+const dom = new JSDOM(html, {
+  runScripts: "dangerously",
+  resources: "usable",
+  virtualConsole
+});
+dom.window.process = process;
+
+dom.window.document.addEventListener("DOMContentLoaded", () => {
+  const angular = dom.window.angular;
+  angular.element(dom.window.document).ready(() => {
+    angular.bootstrap(dom.window.document, ['app']);
+  });
+});
+
diff -Nru angular.js-1.8.3/debian/tests/CVE-2024-21490-PoC.js angular.js-1.8.3/debian/tests/CVE-2024-21490-PoC.js
--- angular.js-1.8.3/debian/tests/CVE-2024-21490-PoC.js	1970-01-01 01:00:00.000000000 +0100
+++ angular.js-1.8.3/debian/tests/CVE-2024-21490-PoC.js	2025-05-11 23:40:38.000000000 +0200
@@ -0,0 +1,96 @@
+#!/usr/bin/env node
+
+const { JSDOM } = require("jsdom");
+const fs = require("fs");
+
+const angularPath = "/usr/share/javascript/angular.js/angular.min.js";
+const angularResource = "/usr/share/javascript/angular.js/angular-resource.min.js";
+const angularMocks = "/usr/share/javascript/angular.js/angular-mocks.js";
+
+const html = `<!DOCTYPE html>
+<html>
+<head>
+  <script src="${angularPath}"></script>
+  <script src="${angularResource}"></script>
+  <script src="${angularMocks}"></script>
+
+  <script>
+    class AppCtrl {
+      static $inject = ['$compile', '$rootScope'];
+
+      ngSrcSet = null;
+      ngSrcSetCompiledElem = null;
+      timeoutId = null;
+      duration = '(N/A)';
+
+      constructor($compile, $rootScope) {
+    this.$compile = $compile;
+    this.$rootScope = $rootScope;
+    this.setNgSrcSetWithSpacesPowerOf2Exponent(20);
+      }
+
+      setNgSrcSetWithSpacesPowerOf2Exponent(exponent) {
+    this.ngSrcSet = 'http://example.com/image.png 2x,'+(' '.repeat(2 ** exponent))+'http://example.com/image.png';
+      }
+
+      compileNgSrcSet() {
+        console.log("compileNgSrcSet called")
+    clearTimeout(this.timeoutId);
+
+    // Use setTimeout to allow manual $apply calls.
+    this.timeoutId = setTimeout(() => {
+      try {
+        console.dir(this.ngSrcSetCompiledElem)
+            this.ngSrcSetCompiledElem[0].innerHtml = (new DOMParser().parseFromString('<img ng-srcset='+this.ngSrcSet+'>','text/html')).body.firstChild;
+        console.log(this.ngSrcSetCompiledElem)
+        const scope = this.ngSrcSetCompiledElem.scope();
+
+        const start = Date.now();
+        //console.log(th)
+        this.$compile(this.ngSrcSetCompiledElem)(scope);
+        this.$rootScope.$apply();
+        const end = Date.now();
+
+        this.duration = ((end - start) / 1000).toFixed(2);
+            console.log(\`Query setup time: \${this.duration} sec\`);
+            if (this.duration > 20) {
+               console.log("[E] It took too long!");
+               window.process.exit(2);
+            } else {
+               window.process.exit(0);
+            }
+      } catch (err) {
+        console.error(err);
+        console.log("[E] crashed!");
+            window.process.exit(3);
+      } finally {
+        this.$rootScope.$apply(); // apply the duration change
+      }
+    });
+      }
+    }
+   // Define and configure the app.
+   angular.module('app', []).controller('AppCtrl', AppCtrl);
+   angular.element(document).ready(() => {
+       angular.bootstrap(document, ['app']); 
+       console.log("angular ready, sending click");
+       setTimeout(() => {
+         document.getElementById("compilebtn").click();
+       }, 50);
+   }); 
+  </script>
+</head>
+<body ng-app="app" ng-controller="AppCtrl as $ctrl">
+  <input class="repro-input" type="url" ng-model="$ctrl.ngSrcSet" />
+  <p ng-ref="$ctrl.ngSrcSetCompiledElem"></p>
+  <button id="compilebtn" ng-click="$ctrl.compileNgSrcSet()">Compile</button>
+</body>
+</html>
+`;
+const dom = new JSDOM(html, {
+  runScripts: "dangerously",
+  resources: "usable",
+  pretendToBeVisual: true,
+  url: `file://${process.cwd()}/debian/build/`
+});
+dom.window.process = process;

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to