Package: release.debian.org Severity: normal X-Debbugs-Cc: angular.js@packages.debian.org, security@debian.org Control: affects -1 + src:angular.js User: release.debian.org@packages.debian.org Usertags: unblock Please unblock package angular.js [ Reason ] Fix 9 CVEs easy to hit for some. Only one is not closed but it need internet explorer [ Impact ] CVEs are opened [ Tests ] jsdom test autopkgtest [ 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 testing [ Other info ] unblock angular.js/1.8.3-3
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-07-19 23:15:59.000000000 +0200
@@ -1,3 +1,67 @@
+angular.js (1.8.3-3) unstable; urgency=medium
+
+ * Team upload
+ * Multi-Arch foreign
+
+ -- Bastien Roucariès <rouca@debian.org> Sat, 19 Jul 2025 23:15:59 +0200
+
+angular.js (1.8.3-2) unstable; 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 <rouca@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-07-19 23:15:21.000000000 +0200
@@ -1,15 +1,19 @@
Source: angular.js
Section: javascript
Priority: optional
-Maintainer: Laszlo Boszormenyi (GCS) <gcs@debian.org>
+Maintainer: Debian Javascript Maintainers <pkg-javascript-devel@lists.alioth.debian.org>
+Uploaders: Laszlo Boszormenyi (GCS) <gcs@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
Depends: ${misc:Depends}
+Multi-Arch: foreign
Description: lets you write client-side web applications as if you had a smarter browser
It lets you use good old HTML (or HAML, Jade and friends) as your template
language and lets you extend HTML's syntax to express your application's
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-07-19 22:50:13.000000000 +0200
@@ -0,0 +1,50 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <rouca@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 <alister@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-07-19 22:50:13.000000000 +0200
@@ -0,0 +1,25 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <rouca@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-07-19 22:50:13.000000000 +0200
@@ -0,0 +1,30 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <rouca@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-07-19 22:50:13.000000000 +0200
@@ -0,0 +1,40 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <rouca@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-07-19 22:50:13.000000000 +0200
@@ -0,0 +1,75 @@
+From: Chris Rowe <chris@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-07-19 22:50:13.000000000 +0200
@@ -0,0 +1,23 @@
+From: Alister Stevens <alister@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-07-19 22:50:13.000000000 +0200
@@ -0,0 +1,30 @@
+From: Alister Stevens <alister@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-07-19 22:50:13.000000000 +0200
@@ -0,0 +1,47 @@
+From: =?utf-8?q?Bastien_Roucari=C3=A8s?= <rouca@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-07-19 22:50:13.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-07-19 22:50:13.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-07-19 22:50:13.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-07-19 22:50:13.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-07-19 22:50:13.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-07-19 22:50:13.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-07-19 22:50:13.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-07-19 22:50:13.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.