Your message dated Fri, 01 Aug 2025 14:05:02 +0000 with message-id <E1uhqNa-005itY-2G@respighi.debian.org> and subject line unblock angular.js has caused the Debian Bug report #1110226, regarding unblock: angular.js/1.8.3-3 to be marked as done. This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact owner@bugs.debian.org immediately.) -- 1110226: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1110226 Debian Bug Tracking System Contact owner@bugs.debian.org with problems
--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: unblock: angular.js/1.8.3-3
- From: Bastien Roucaries <rouca@debian.org>
- Date: Fri, 01 Aug 2025 15:30:04 +0200
- Message-id: <[🔎] 3972575.kC03pvyZki@debian-ei>
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-3diff -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.
--- End Message ---
--- Begin Message ---
- To: 1110226-done@bugs.debian.org
- Subject: unblock angular.js
- From: Ivo De Decker <ivodd@respighi.debian.org>
- Date: Fri, 01 Aug 2025 14:05:02 +0000
- Message-id: <E1uhqNa-005itY-2G@respighi.debian.org>
Unblocked angular.js.
--- End Message ---