Refine your search

4 vulnerabilities found for hex_core by hexpm

CVE-2026-96596 (GCVE-0-2026-96596)
Vulnerability from cvelistv5
Published
2026-10-14 16:56
Modified
2026-10-22 07:08
CWE
  • CWE-835 - Loop with Unreachable Exit Condition ('Infinite Loop')
Summary
Loop with Unreachable Exit Condition ('Infinite Loop') vulnerability in Erlang OTP stdlib (erl_tar module), hexpm hex_core (hex_erl_tar module), hexpm hex (mix_hex_erl_tar module) and erlang rebar3 (r3_hex_erl_tar module) allows an attacker who supplies a tar archive to cause a denial of service via a crafted GNU sparse member. When erl_tar:extract/1,2 writes a member to disk, erl_tar:stream_to_file_loop/3 reads it in chunks of 65536 bytes by default. For a GNU sparse member whose sparse map ends before its real size, erl_tar:do_sparse_read/3 matches its trailing-hole clause before its zero-length clause. After the chunk is used up, the trailing-hole clause reads zero bytes, does not advance the position, and recurses forever. A 2048-byte archive keeps the extracting process and one scheduler busy until the process is killed. The {max_size, N} option prevents this only when N is below the real size of the member. Extraction with the memory option is not affected. hex_core ships its own copy of erl_tar as hex_erl_tar, and Hex and rebar3 ship hex_core with prefixed module names (mix_hex_erl_tar and r3_hex_erl_tar). These copies contain the same code and do not call stdlib's erl_tar, so they are affected on any OTP version. OTP 28 is not affected, but an application running on OTP 28 is affected if it extracts archives through an affected version of hex_core, Hex or rebar3. This issue affects OTP from OTPĀ 29.0 before OTPĀ 29.1.2, corresponding to rebar3 from 3.27.1 before 3.28.0, and stdlib from 8.0 before 8.1.1, and hex from 2.4.2 before 2.5.3; hex_core: from 0.14.0 before 0.20.1.
Impacted products
Vendor Product Version
erlang rebar3 Version: 3.27.1   ≤
    cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*
Create a notification for this product.
   erlang rebar3 Version: 23dbdb5d1f87f56902aef296c88a20049cd0c6e4
    cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex_core Version: 0.14.0   ≤
    cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex_core Version: 13bb9fbba418a406af614790b8d5cd458259ee70
    cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*
Create a notification for this product.
   Erlang OTP Version: 29.0
    cpe:2.3:a:erlang:erlang\/otp:*:*:*:*:*:*:*:*
Create a notification for this product.
   Erlang OTP Version: 8.0
    cpe:2.3:a:erlang:erlang\/otp:*:*:*:*:*:*:*:*
Create a notification for this product.
   Erlang OTP Version: fbf2c7194f6fce4b7b66dc0bcaa4f6b4b85e088f
    cpe:2.3:a:erlang:erlang\/otp:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex Version: 2.4.2   ≤
    cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex Version: 5543a1919c709d8eb2b317f62aad76ca1eed375c
    cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*
Create a notification for this product.
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2026-96596",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-10-16T20:07:46.754736Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2026-10-16T20:08:17.542Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      }
    ],
    "cna": {
      "affected": [
        {
          "cpes": [
            "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "r3_hex_erl_tar",
            "r3_hex_tarball"
          ],
          "packageName": "rebar3",
          "packageURL": "pkg:otp/rebar3?repository_url=https:%2F%2Fgithub.com%2Ferlang%2Frebar3\u0026vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Ferlang%2Frebar3.git",
          "product": "rebar3",
          "programFiles": [
            "apps/rebar/src/vendored/r3_hex_erl_tar.erl",
            "apps/rebar/src/vendored/r3_hex_tarball.erl"
          ],
          "programRoutines": [
            {
              "name": "r3_hex_erl_tar:do_sparse_read/3"
            },
            {
              "name": "r3_hex_erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "r3_hex_erl_tar:extract/1"
            },
            {
              "name": "r3_hex_erl_tar:extract/2"
            },
            {
              "name": "r3_hex_tarball:unpack/2"
            },
            {
              "name": "r3_hex_tarball:unpack/3"
            },
            {
              "name": "r3_hex_tarball:unpack_docs/2"
            },
            {
              "name": "r3_hex_tarball:unpack_docs/3"
            }
          ],
          "repo": "https://github.com/erlang/rebar3",
          "vendor": "erlang",
          "versions": [
            {
              "lessThan": "3.28.0",
              "status": "affected",
              "version": "3.27.1",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "r3_hex_erl_tar",
            "r3_hex_tarball"
          ],
          "packageName": "erlang/rebar3",
          "packageURL": "pkg:github/erlang/rebar3",
          "product": "rebar3",
          "programFiles": [
            "apps/rebar/src/vendored/r3_hex_erl_tar.erl",
            "apps/rebar/src/vendored/r3_hex_tarball.erl"
          ],
          "programRoutines": [
            {
              "name": "r3_hex_erl_tar:do_sparse_read/3"
            },
            {
              "name": "r3_hex_erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "r3_hex_erl_tar:extract/1"
            },
            {
              "name": "r3_hex_erl_tar:extract/2"
            },
            {
              "name": "r3_hex_tarball:unpack/2"
            },
            {
              "name": "r3_hex_tarball:unpack/3"
            },
            {
              "name": "r3_hex_tarball:unpack_docs/2"
            },
            {
              "name": "r3_hex_tarball:unpack_docs/3"
            }
          ],
          "repo": "https://github.com/erlang/rebar3",
          "vendor": "erlang",
          "versions": [
            {
              "lessThan": "310e2ec8c7dd3df05d67af2b7fae23f30fc523c4",
              "status": "affected",
              "version": "23dbdb5d1f87f56902aef296c88a20049cd0c6e4",
              "versionType": "git"
            }
          ]
        },
        {
          "collectionURL": "https://repo.hex.pm",
          "cpes": [
            "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "hex_erl_tar",
            "hex_tarball"
          ],
          "packageName": "hex_core",
          "packageURL": "pkg:hex/hex_core",
          "product": "hex_core",
          "programFiles": [
            "src/hex_erl_tar.erl",
            "src/hex_tarball.erl"
          ],
          "programRoutines": [
            {
              "name": "hex_erl_tar:do_sparse_read/3"
            },
            {
              "name": "hex_erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "hex_erl_tar:extract/1"
            },
            {
              "name": "hex_erl_tar:extract/2"
            },
            {
              "name": "hex_tarball:unpack/2"
            },
            {
              "name": "hex_tarball:unpack/3"
            },
            {
              "name": "hex_tarball:unpack_docs/2"
            },
            {
              "name": "hex_tarball:unpack_docs/3"
            }
          ],
          "repo": "https://github.com/hexpm/hex_core",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "0.20.1",
              "status": "affected",
              "version": "0.14.0",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "hex_erl_tar",
            "hex_tarball"
          ],
          "packageName": "hexpm/hex_core",
          "packageURL": "pkg:github/hexpm/hex_core",
          "product": "hex_core",
          "programFiles": [
            "src/hex_erl_tar.erl",
            "src/hex_tarball.erl"
          ],
          "programRoutines": [
            {
              "name": "hex_erl_tar:do_sparse_read/3"
            },
            {
              "name": "hex_erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "hex_erl_tar:extract/1"
            },
            {
              "name": "hex_erl_tar:extract/2"
            },
            {
              "name": "hex_tarball:unpack/2"
            },
            {
              "name": "hex_tarball:unpack/3"
            },
            {
              "name": "hex_tarball:unpack_docs/2"
            },
            {
              "name": "hex_tarball:unpack_docs/3"
            }
          ],
          "repo": "https://github.com/hexpm/hex_core",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "a2ece683e6e88a3ec95ad20b09aca426e08b372e",
              "status": "affected",
              "version": "13bb9fbba418a406af614790b8d5cd458259ee70",
              "versionType": "git"
            }
          ]
        },
        {
          "cpes": [
            "cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "erl_tar"
          ],
          "packageName": "otp",
          "packageURL": "pkg:software-id/erlang.org/otp",
          "product": "OTP",
          "programFiles": [
            "lib/stdlib/src/erl_tar.erl"
          ],
          "programRoutines": [
            {
              "name": "erl_tar:do_sparse_read/3"
            },
            {
              "name": "erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "erl_tar:extract/1"
            },
            {
              "name": "erl_tar:extract/2"
            }
          ],
          "vendor": "Erlang",
          "versions": [
            {
              "lessThan": "29.1.2",
              "status": "affected",
              "version": "29.0",
              "versionType": "otp"
            }
          ]
        },
        {
          "cpes": [
            "cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "erl_tar"
          ],
          "packageName": "stdlib",
          "packageURL": "pkg:otp/stdlib?repository_url=https:%2F%2Fgithub.com%2Ferlang%2Fotp\u0026vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Ferlang%2Fotp.git",
          "product": "OTP",
          "programFiles": [
            "src/erl_tar.erl"
          ],
          "programRoutines": [
            {
              "name": "erl_tar:do_sparse_read/3"
            },
            {
              "name": "erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "erl_tar:extract/1"
            },
            {
              "name": "erl_tar:extract/2"
            }
          ],
          "repo": "https://github.com/erlang/otp",
          "vendor": "Erlang",
          "versions": [
            {
              "lessThan": "8.1.1",
              "status": "affected",
              "version": "8.0",
              "versionType": "otp"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "erl_tar"
          ],
          "packageName": "erlang/otp",
          "packageURL": "pkg:github/erlang/otp",
          "product": "OTP",
          "programFiles": [
            "lib/stdlib/src/erl_tar.erl"
          ],
          "programRoutines": [
            {
              "name": "erl_tar:do_sparse_read/3"
            },
            {
              "name": "erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "erl_tar:extract/1"
            },
            {
              "name": "erl_tar:extract/2"
            }
          ],
          "repo": "https://github.com/erlang/otp",
          "vendor": "Erlang",
          "versions": [
            {
              "lessThan": "3086307f311b78b38644a7787a3aca6a3f95a9d5",
              "status": "affected",
              "version": "fbf2c7194f6fce4b7b66dc0bcaa4f6b4b85e088f",
              "versionType": "git"
            }
          ]
        },
        {
          "cpes": [
            "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "mix_hex_erl_tar",
            "mix_hex_tarball"
          ],
          "packageName": "hex",
          "packageURL": "pkg:otp/hex?repository_url=https:%2F%2Fgithub.com%2Fhexpm%2Fhex\u0026vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Fhexpm%2Fhex.git",
          "product": "hex",
          "programFiles": [
            "src/mix_hex_erl_tar.erl",
            "src/mix_hex_tarball.erl"
          ],
          "programRoutines": [
            {
              "name": "mix_hex_erl_tar:do_sparse_read/3"
            },
            {
              "name": "mix_hex_erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "mix_hex_erl_tar:extract/1"
            },
            {
              "name": "mix_hex_erl_tar:extract/2"
            },
            {
              "name": "mix_hex_tarball:unpack/2"
            },
            {
              "name": "mix_hex_tarball:unpack/3"
            },
            {
              "name": "mix_hex_tarball:unpack_docs/2"
            },
            {
              "name": "mix_hex_tarball:unpack_docs/3"
            }
          ],
          "repo": "https://github.com/hexpm/hex",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "2.5.3",
              "status": "affected",
              "version": "2.4.2",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "mix_hex_erl_tar",
            "mix_hex_tarball"
          ],
          "packageName": "hexpm/hex",
          "packageURL": "pkg:github/hexpm/hex",
          "product": "hex",
          "programFiles": [
            "src/mix_hex_erl_tar.erl",
            "src/mix_hex_tarball.erl"
          ],
          "programRoutines": [
            {
              "name": "mix_hex_erl_tar:do_sparse_read/3"
            },
            {
              "name": "mix_hex_erl_tar:stream_to_file_loop/3"
            },
            {
              "name": "mix_hex_erl_tar:extract/1"
            },
            {
              "name": "mix_hex_erl_tar:extract/2"
            },
            {
              "name": "mix_hex_tarball:unpack/2"
            },
            {
              "name": "mix_hex_tarball:unpack/3"
            },
            {
              "name": "mix_hex_tarball:unpack_docs/2"
            },
            {
              "name": "mix_hex_tarball:unpack_docs/3"
            }
          ],
          "repo": "https://github.com/hexpm/hex",
          "vendor": "hexpm",
          "versions": [
            {
              "changes": [
                {
                  "at": "8e1067131a13949eff30623f31648a945ffd5418",
                  "status": "unaffected"
                },
                {
                  "at": "7847c23d09ab52113614c3718e1e7d368743da5d",
                  "status": "unaffected"
                }
              ],
              "lessThan": "*",
              "status": "affected",
              "version": "5543a1919c709d8eb2b317f62aad76ca1eed375c",
              "versionType": "git"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "3.28.0",
                  "versionStartIncluding": "3.27.1",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "0.20.1",
                  "versionStartIncluding": "0.14.0",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:a:erlang:erlang\\/otp:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "29.1.2",
                  "versionStartIncluding": "29.0",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "2.5.3",
                  "versionStartIncluding": "2.4.2",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ],
          "operator": "AND"
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Eric Meadows-J\u00f6nsson"
        },
        {
          "lang": "en",
          "type": "reporter",
          "value": "Eric Meadows-J\u00f6nsson"
        }
      ],
      "dateAssigned": "2026-10-07T13:11:38.000Z",
      "datePublic": "2026-10-14T16:56:18.000Z",
      "descriptions": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eLoop with Unreachable Exit Condition (\u0027Infinite Loop\u0027) vulnerability in Erlang OTP stdlib (\u003ccode\u003eerl_tar\u003c/code\u003e module), hexpm hex_core (\u003ccode\u003ehex_erl_tar\u003c/code\u003e module), hexpm hex (\u003ccode\u003emix_hex_erl_tar\u003c/code\u003e module) and erlang rebar3 (\u003ccode\u003er3_hex_erl_tar\u003c/code\u003e module) allows an attacker who supplies a tar archive to cause a denial of service via a crafted GNU sparse member.\u003c/p\u003e\n\u003cp\u003eWhen \u003ccode\u003eerl_tar:extract/1,2\u003c/code\u003e writes a member to disk, \u003ccode\u003eerl_tar:stream_to_file_loop/3\u003c/code\u003e reads it in chunks of 65536 bytes by default. For a GNU sparse member whose sparse map ends before its real size, \u003ccode\u003eerl_tar:do_sparse_read/3\u003c/code\u003e matches its trailing-hole clause before its zero-length clause. After the chunk is used up, the trailing-hole clause reads zero bytes, does not advance the position, and recurses forever. A 2048-byte archive keeps the extracting process and one scheduler busy until the process is killed. The \u003ccode\u003e{max_size, N}\u003c/code\u003e option prevents this only when N is below the real size of the member. Extraction with the \u003ccode\u003ememory\u003c/code\u003e option is not affected.\u003c/p\u003e\n\u003cp\u003ehex_core ships its own copy of \u003ccode\u003eerl_tar\u003c/code\u003e as \u003ccode\u003ehex_erl_tar\u003c/code\u003e, and Hex and rebar3 ship hex_core with prefixed module names (\u003ccode\u003emix_hex_erl_tar\u003c/code\u003e and \u003ccode\u003er3_hex_erl_tar\u003c/code\u003e). These copies contain the same code and do not call stdlib\u0027s \u003ccode\u003eerl_tar\u003c/code\u003e, so they are affected on any OTP version. OTP 28 is not affected, but an application running on OTP 28 is affected if it extracts archives through an affected version of hex_core, Hex or rebar3.\u003c/p\u003e\n\u003cp\u003eThis issue affects OTP from OTP\u0026nbsp;29.0 before OTP\u0026nbsp;29.1.2, corresponding to rebar3 from 3.27.1 before 3.28.0, and stdlib from 8.0 before 8.1.1, and hex from 2.4.2 before 2.5.3; hex_core: from 0.14.0 before 0.20.1.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Loop with Unreachable Exit Condition (\u0027Infinite Loop\u0027) vulnerability in Erlang OTP stdlib (`erl_tar` module), hexpm hex_core (`hex_erl_tar` module), hexpm hex (`mix_hex_erl_tar` module) and erlang rebar3 (`r3_hex_erl_tar` module) allows an attacker who supplies a tar archive to cause a denial of service via a crafted GNU sparse member.\n\nWhen `erl_tar:extract/1,2` writes a member to disk, `erl_tar:stream_to_file_loop/3` reads it in chunks of 65536 bytes by default. For a GNU sparse member whose sparse map ends before its real size, `erl_tar:do_sparse_read/3` matches its trailing-hole clause before its zero-length clause. After the chunk is used up, the trailing-hole clause reads zero bytes, does not advance the position, and recurses forever. A 2048-byte archive keeps the extracting process and one scheduler busy until the process is killed. The `{max_size, N}` option prevents this only when N is below the real size of the member. Extraction with the `memory` option is not affected.\n\nhex_core ships its own copy of `erl_tar` as `hex_erl_tar`, and Hex and rebar3 ship hex_core with prefixed module names (`mix_hex_erl_tar` and `r3_hex_erl_tar`). These copies contain the same code and do not call stdlib\u0027s `erl_tar`, so they are affected on any OTP version. OTP 28 is not affected, but an application running on OTP 28 is affected if it extracts archives through an affected version of hex_core, Hex or rebar3.\n\nThis issue affects OTP from OTP\u00a029.0 before OTP\u00a029.1.2, corresponding to rebar3 from 3.27.1 before 3.28.0, and stdlib from 8.0 before 8.1.1, and hex from 2.4.2 before 2.5.3; hex_core: from 0.14.0 before 0.20.1."
            }
          ],
          "value": "Loop with Unreachable Exit Condition (\u0027Infinite Loop\u0027) vulnerability in Erlang OTP stdlib (erl_tar module), hexpm hex_core (hex_erl_tar module), hexpm hex (mix_hex_erl_tar module) and erlang rebar3 (r3_hex_erl_tar module) allows an attacker who supplies a tar archive to cause a denial of service via a crafted GNU sparse member.\n\nWhen erl_tar:extract/1,2 writes a member to disk, erl_tar:stream_to_file_loop/3 reads it in chunks of 65536 bytes by default. For a GNU sparse member whose sparse map ends before its real size, erl_tar:do_sparse_read/3 matches its trailing-hole clause before its zero-length clause. After the chunk is used up, the trailing-hole clause reads zero bytes, does not advance the position, and recurses forever. A 2048-byte archive keeps the extracting process and one scheduler busy until the process is killed. The {max_size, N} option prevents this only when N is below the real size of the member. Extraction with the memory option is not affected.\n\nhex_core ships its own copy of erl_tar as hex_erl_tar, and Hex and rebar3 ship hex_core with prefixed module names (mix_hex_erl_tar and r3_hex_erl_tar). These copies contain the same code and do not call stdlib\u0027s erl_tar, so they are affected on any OTP version. OTP 28 is not affected, but an application running on OTP 28 is affected if it extracts archives through an affected version of hex_core, Hex or rebar3.\n\nThis issue affects OTP from OTP\u00a029.0 before OTP\u00a029.1.2, corresponding to rebar3 from 3.27.1 before 3.28.0, and stdlib from 8.0 before 8.1.1, and hex from 2.4.2 before 2.5.3; hex_core: from 0.14.0 before 0.20.1."
        }
      ],
      "impacts": [
        {
          "capecId": "CAPEC-130",
          "descriptions": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eAn attacker who can get an application to extract a tar archive to disk keeps the extracting process and one scheduler busy forever. Each further archive occupies another scheduler, until the node stops responding.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "An attacker who can get an application to extract a tar archive to disk keeps the extracting process and one scheduler busy forever. Each further archive occupies another scheduler, until the node stops responding."
                }
              ],
              "value": "An attacker who can get an application to extract a tar archive to disk keeps the extracting process and one scheduler busy forever. Each further archive occupies another scheduler, until the node stops responding."
            }
          ]
        }
      ],
      "metrics": [
        {
          "cvssV4_0": {
            "Automatable": "NOT_DEFINED",
            "Recovery": "NOT_DEFINED",
            "Safety": "NOT_DEFINED",
            "attackComplexity": "LOW",
            "attackRequirements": "PRESENT",
            "attackVector": "LOCAL",
            "baseScore": 5.9,
            "baseSeverity": "MEDIUM",
            "privilegesRequired": "NONE",
            "providerUrgency": "NOT_DEFINED",
            "subAvailabilityImpact": "NONE",
            "subConfidentialityImpact": "NONE",
            "subIntegrityImpact": "NONE",
            "userInteraction": "NONE",
            "valueDensity": "NOT_DEFINED",
            "vectorString": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
            "version": "4.0",
            "vulnAvailabilityImpact": "HIGH",
            "vulnConfidentialityImpact": "NONE",
            "vulnIntegrityImpact": "NONE",
            "vulnerabilityResponseEffort": "NOT_DEFINED"
          },
          "format": "CVSS",
          "scenarios": [
            {
              "lang": "en",
              "value": "GENERAL"
            }
          ]
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-835",
              "description": "CWE-835 Loop with Unreachable Exit Condition (\u0027Infinite Loop\u0027)",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-10-22T07:08:09.364Z",
        "orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "shortName": "EEF"
      },
      "references": [
        {
          "name": "GitHub Advisory",
          "tags": [
            "related",
            "vendor-advisory"
          ],
          "url": "https://github.com/erlang/otp/security/advisories/GHSA-phm5-m6cj-5382"
        },
        {
          "name": "EEF CNA record for CVE-2026-96596",
          "tags": [
            "related"
          ],
          "url": "https://cna.erlef.org/cves/CVE-2026-96596.html"
        },
        {
          "name": "OSV record EEF-CVE-2026-96596",
          "tags": [
            "related"
          ],
          "url": "https://osv.dev/vulnerability/EEF-CVE-2026-96596"
        },
        {
          "name": "Erlang/OTP version ordering",
          "tags": [
            "x_version-scheme"
          ],
          "url": "https://www.erlang.org/doc/system/versions.html#order-of-versions"
        },
        {
          "name": "Introducing commit 23dbdb5 in erlang/rebar3",
          "tags": [
            "related"
          ],
          "url": "https://github.com/erlang/rebar3/commit/23dbdb5d1f87f56902aef296c88a20049cd0c6e4"
        },
        {
          "name": "Fix commit 310e2ec in erlang/rebar3",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/erlang/rebar3/commit/310e2ec8c7dd3df05d67af2b7fae23f30fc523c4"
        },
        {
          "name": "Introducing commit 13bb9fb in hexpm/hex_core",
          "tags": [
            "related"
          ],
          "url": "https://github.com/hexpm/hex_core/commit/13bb9fbba418a406af614790b8d5cd458259ee70"
        },
        {
          "name": "Fix commit a2ece68 in hexpm/hex_core",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/hexpm/hex_core/commit/a2ece683e6e88a3ec95ad20b09aca426e08b372e"
        },
        {
          "name": "Introducing commit fbf2c71 in erlang/otp",
          "tags": [
            "related"
          ],
          "url": "https://github.com/erlang/otp/commit/fbf2c7194f6fce4b7b66dc0bcaa4f6b4b85e088f"
        },
        {
          "name": "Fix commit 3086307 in erlang/otp",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/erlang/otp/commit/3086307f311b78b38644a7787a3aca6a3f95a9d5"
        },
        {
          "name": "Introducing commit 5543a19 in hexpm/hex",
          "tags": [
            "related"
          ],
          "url": "https://github.com/hexpm/hex/commit/5543a1919c709d8eb2b317f62aad76ca1eed375c"
        },
        {
          "name": "Fix commit 8e10671 in hexpm/hex",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/hexpm/hex/commit/8e1067131a13949eff30623f31648a945ffd5418"
        },
        {
          "name": "Fix commit 7847c23 in hexpm/hex",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/hexpm/hex/commit/7847c23d09ab52113614c3718e1e7d368743da5d"
        }
      ],
      "source": {
        "discovery": "EXTERNAL"
      },
      "title": "erl_tar:extract/2 loops forever on a GNU sparse member with a trailing hole",
      "workarounds": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003ePass \u003ccode\u003e{chunks, N}\u003c/code\u003e together with \u003ccode\u003e{max_size, N}\u003c/code\u003e, with the same value N, to \u003ccode\u003eerl_tar:extract/2\u003c/code\u003e. Extraction then rejects any member larger than N, and reads each remaining member in one call, so the loop cannot occur.\u003c/p\u003e\n\u003cp\u003eAlternatively, extract with the \u003ccode\u003ememory\u003c/code\u003e option and write the returned files to disk in the application.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Pass `{chunks, N}` together with `{max_size, N}`, with the same value N, to `erl_tar:extract/2`. Extraction then rejects any member larger than N, and reads each remaining member in one call, so the loop cannot occur.\n\nAlternatively, extract with the `memory` option and write the returned files to disk in the application."
            }
          ],
          "value": "Pass {chunks, N} together with {max_size, N}, with the same value N, to erl_tar:extract/2. Extraction then rejects any member larger than N, and reads each remaining member in one call, so the loop cannot occur.\n\nAlternatively, extract with the memory option and write the returned files to disk in the application."
        }
      ],
      "x_proofOfConcept": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003col\u003e\n\u003cli\u003eBuild a 2048-byte tar that holds one GNU sparse member (typeflag \u003ccode\u003eS\u003c/code\u003e). Give it a stored size of 4 bytes, one sparse map entry of 4 bytes at offset 0, and a real size of 1048576 bytes. Follow the 512-byte header with a 512-byte block that starts with the 4 data bytes, then 1024 zero bytes.\u003c/li\u003e\n\u003cli\u003eIn a separate process, call \u003ccode\u003eerl_tar:extract({binary, Tar}, [{cwd, Dir}])\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eThe call does not return. After 5 seconds the process has used more than 10^9 reductions. On OTP 28 the same call returns \u003ccode\u003eok\u003c/code\u003e.\u003c/li\u003e\n\u003c/ol\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "1. Build a 2048-byte tar that holds one GNU sparse member (typeflag `S`). Give it a stored size of 4 bytes, one sparse map entry of 4 bytes at offset 0, and a real size of 1048576 bytes. Follow the 512-byte header with a 512-byte block that starts with the 4 data bytes, then 1024 zero bytes.\n2. In a separate process, call `erl_tar:extract({binary, Tar}, [{cwd, Dir}])`.\n3. The call does not return. After 5 seconds the process has used more than 10^9 reductions. On OTP 28 the same call returns `ok`."
            }
          ],
          "value": "* Build a 2048-byte tar that holds one GNU sparse member (typeflag S). Give it a stored size of 4 bytes, one sparse map entry of 4 bytes at offset 0, and a real size of 1048576 bytes. Follow the 512-byte header with a 512-byte block that starts with the 4 data bytes, then 1024 zero bytes.\n* In a separate process, call erl_tar:extract({binary, Tar}, [{cwd, Dir}]).\n* The call does not return. After 5 seconds the process has used more than 10^9 reductions. On OTP 28 the same call returns ok."
        }
      ],
      "x_technicalAnalysis": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003e\u003cstrong\u003e1. Chunked extraction.\u003c/strong\u003e \u003ccode\u003eerl_tar:extract/2\u003c/code\u003e writes each member to disk through \u003ccode\u003estream_to_file_loop/3\u003c/code\u003e. This function calls \u003ccode\u003edo_read(Reader, ChunkSize)\u003c/code\u003e until the \u003ccode\u003enum_bytes\u003c/code\u003e field of the reader is 0. The default chunk size is 65536 bytes.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. Clause order in \u003ccode\u003edo_sparse_read/3\u003c/code\u003e.\u003c/strong\u003e For a sparse member, \u003ccode\u003edo_read/2\u003c/code\u003e calls \u003ccode\u003edo_sparse_read/3\u003c/code\u003e. The clause for a trailing hole matches when \u003ccode\u003esparse_map\u003c/code\u003e is \u003ccode\u003e[]\u003c/code\u003e and \u003ccode\u003ePos \u0026lt; Size\u003c/code\u003e. It comes before the clause that returns when \u003ccode\u003eLen\u003c/code\u003e is 0.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. Unbounded recursion.\u003c/strong\u003e The member is a GNU sparse member (typeflag \u003ccode\u003eS\u003c/code\u003e) whose real size is larger than one chunk and whose sparse map ends before the real size. After the data fragments, the trailing-hole clause reads the rest of the chunk and recurses with \u003ccode\u003eLen = 0\u003c/code\u003e. The same clause matches again, and \u003ccode\u003eread_sparse_hole/3\u003c/code\u003e returns an empty binary and leaves \u003ccode\u003ePos\u003c/code\u003e unchanged. The zero-length clause is never reached, so the call never returns.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e4. No mitigation from \u003ccode\u003emax_size\u003c/code\u003e.\u003c/strong\u003e For a sparse member, \u003ccode\u003e{max_size, N}\u003c/code\u003e is checked against the real size from the header. It stops the loop only when N is below that size. \u003ccode\u003eerl_tar:table/2\u003c/code\u003e lists the member as \u003ccode\u003eregular\u003c/code\u003e, so a caller cannot skip sparse members by type.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "**1. Chunked extraction.** `erl_tar:extract/2` writes each member to disk through `stream_to_file_loop/3`. This function calls `do_read(Reader, ChunkSize)` until the `num_bytes` field of the reader is 0. The default chunk size is 65536 bytes.\n\n**2. Clause order in `do_sparse_read/3`.** For a sparse member, `do_read/2` calls `do_sparse_read/3`. The clause for a trailing hole matches when `sparse_map` is `[]` and `Pos \u003c Size`. It comes before the clause that returns when `Len` is 0.\n\n**3. Unbounded recursion.** The member is a GNU sparse member (typeflag `S`) whose real size is larger than one chunk and whose sparse map ends before the real size. After the data fragments, the trailing-hole clause reads the rest of the chunk and recurses with `Len = 0`. The same clause matches again, and `read_sparse_hole/3` returns an empty binary and leaves `Pos` unchanged. The zero-length clause is never reached, so the call never returns.\n\n**4. No mitigation from `max_size`.** For a sparse member, `{max_size, N}` is checked against the real size from the header. It stops the loop only when N is below that size. `erl_tar:table/2` lists the member as `regular`, so a caller cannot skip sparse members by type."
            }
          ],
          "value": "1. Chunked extraction. erl_tar:extract/2 writes each member to disk through stream_to_file_loop/3. This function calls do_read(Reader, ChunkSize) until the num_bytes field of the reader is 0. The default chunk size is 65536 bytes.\n\n2. Clause order in do_sparse_read/3. For a sparse member, do_read/2 calls do_sparse_read/3. The clause for a trailing hole matches when sparse_map is [] and Pos \u003c Size. It comes before the clause that returns when Len is 0.\n\n3. Unbounded recursion. The member is a GNU sparse member (typeflag S) whose real size is larger than one chunk and whose sparse map ends before the real size. After the data fragments, the trailing-hole clause reads the rest of the chunk and recurses with Len = 0. The same clause matches again, and read_sparse_hole/3 returns an empty binary and leaves Pos unchanged. The zero-length clause is never reached, so the call never returns.\n\n4. No mitigation from max_size. For a sparse member, {max_size, N} is checked against the real size from the header. It stops the loop only when N is below that size. erl_tar:table/2 lists the member as regular, so a caller cannot skip sparse members by type."
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
    "assignerShortName": "EEF",
    "cveId": "CVE-2026-96596",
    "datePublished": "2026-10-14T16:56:18.530Z",
    "dateReserved": "2026-09-27T12:00:01.540Z",
    "dateUpdated": "2026-10-22T07:08:09.364Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

CVE-2026-105274 (GCVE-0-2026-105274)
Vulnerability from cvelistv5
Published
2026-10-12 16:43
Modified
2026-10-15 18:05
CWE
  • CWE-409 - Improper Handling of Highly Compressed Data (Data Amplification)
Summary
Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in hexpm hex_core allows an untrusted repository mirror, or a server answering hex_core's API requests, to exhaust the memory of the Erlang VM running hex_core. The same code is vendored in Hex (mix_hex_repo, mix_hex_api) and rebar3 (r3_hex_repo, r3_hex_api). hex_repo:get_names/1, hex_repo:get_versions/1, hex_repo:get_package/2 and hex_repo:get_policy/2 decompress the registry response with zlib:gunzip/1 and decode the signed envelope before verifying its signature. A mirror doesn't have the repository's private key, but it chooses the compressed bytes, so a small response decompresses into an envelope of any size before the signature check rejects it. hex_api decodes responses with the application/vnd.hex+erlang content type through hex_safe_binary_to_term:safe_binary_to_term/1, which calls binary_to_term(Binary, [safe]). The safe option prevents atom creation, but it accepts compressed terms and doesn't limit the size of the decoded term, and the check that rejects functions and ports runs after the term has been built. The fix for CVE-2026-21619 added the safe option and that check without bounding the decoded size. This issue affects rebar3: from 3.9.1 before 3.27.3; hex: from 2.1.0 before 2.5.2; hex_core: from 0.1.0 before 0.20.0.
Impacted products
Vendor Product Version
erlang rebar3 Version: 3.9.1   ≤
    cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*
Create a notification for this product.
   erlang rebar3 Version: 209c02ec57c2cc3207ee0174c3af3675b8dc8f79
    cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex_core Version: 0.1.0   ≤
    cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex_core Version: fbb6d9de472e5edb8d6fb6b32a91cb266137892e
    cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex Version: 2.1.0   ≤
    cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex Version: 671f695ac548ed01f5828c2a739ecaa942b21007
    cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*
Create a notification for this product.
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2026-105274",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-10-15T17:51:41.556015Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2026-10-15T18:05:12.446Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      }
    ],
    "cna": {
      "affected": [
        {
          "cpes": [
            "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "r3_hex_repo",
            "r3_hex_api"
          ],
          "packageName": "rebar3",
          "packageURL": "pkg:otp/rebar3?repository_url=https:%2F%2Fgithub.com%2Ferlang%2Frebar3\u0026vcs_url=repository_url=git%2Bhttps:%2F%2Fgithub.com%2Ferlang%2Frebar3.git",
          "product": "rebar3",
          "programFiles": [
            "apps/rebar/src/vendored/r3_hex_repo.erl",
            "apps/rebar/src/vendored/r3_hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "r3_hex_repo:get_names/1"
            },
            {
              "name": "r3_hex_repo:get_versions/1"
            },
            {
              "name": "r3_hex_repo:get_package/2"
            },
            {
              "name": "r3_hex_api:request/4"
            }
          ],
          "repo": "https://github.com/erlang/rebar3",
          "vendor": "erlang",
          "versions": [
            {
              "lessThan": "3.27.3",
              "status": "affected",
              "version": "3.9.1",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "r3_hex_repo",
            "r3_hex_api"
          ],
          "packageName": "erlang/rebar3",
          "packageURL": "pkg:github/erlang/rebar3",
          "product": "rebar3",
          "programFiles": [
            "apps/rebar/src/vendored/r3_hex_repo.erl",
            "apps/rebar/src/vendored/r3_hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "r3_hex_repo:get_names/1"
            },
            {
              "name": "r3_hex_repo:get_versions/1"
            },
            {
              "name": "r3_hex_repo:get_package/2"
            },
            {
              "name": "r3_hex_api:request/4"
            }
          ],
          "repo": "https://github.com/erlang/rebar3",
          "vendor": "erlang",
          "versions": [
            {
              "lessThan": "360838a22f5b3a88c0358207f2923059bcbb3afb",
              "status": "affected",
              "version": "209c02ec57c2cc3207ee0174c3af3675b8dc8f79",
              "versionType": "git"
            }
          ]
        },
        {
          "collectionURL": "https://repo.hex.pm",
          "cpes": [
            "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "hex_repo",
            "hex_api",
            "hex_safe_binary_to_term"
          ],
          "packageName": "hex_core",
          "packageURL": "pkg:hex/hex_core",
          "product": "hex_core",
          "programFiles": [
            "src/hex_repo.erl",
            "src/hex_api.erl",
            "src/hex_safe_binary_to_term.erl"
          ],
          "programRoutines": [
            {
              "name": "hex_repo:get_names/1"
            },
            {
              "name": "hex_repo:get_versions/1"
            },
            {
              "name": "hex_repo:get_package/2"
            },
            {
              "name": "hex_repo:get_policy/2"
            },
            {
              "name": "hex_api:request/4"
            },
            {
              "name": "hex_safe_binary_to_term:safe_binary_to_term/1"
            }
          ],
          "repo": "https://github.com/hexpm/hex_core",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "0.20.0",
              "status": "affected",
              "version": "0.1.0",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "hex_repo",
            "hex_api",
            "hex_safe_binary_to_term"
          ],
          "packageName": "hexpm/hex_core",
          "packageURL": "pkg:github/hexpm/hex_core",
          "product": "hex_core",
          "programFiles": [
            "src/hex_repo.erl",
            "src/hex_api.erl",
            "src/hex_safe_binary_to_term.erl"
          ],
          "programRoutines": [
            {
              "name": "hex_repo:get_names/1"
            },
            {
              "name": "hex_repo:get_versions/1"
            },
            {
              "name": "hex_repo:get_package/2"
            },
            {
              "name": "hex_repo:get_policy/2"
            },
            {
              "name": "hex_api:request/4"
            },
            {
              "name": "hex_safe_binary_to_term:safe_binary_to_term/1"
            }
          ],
          "repo": "https://github.com/hexpm/hex_core",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "ebe25d110717f6a3addba5232cd4a7dc1c76b628",
              "status": "affected",
              "version": "fbb6d9de472e5edb8d6fb6b32a91cb266137892e",
              "versionType": "git"
            }
          ]
        },
        {
          "cpes": [
            "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "mix_hex_repo",
            "mix_hex_api"
          ],
          "packageName": "hex",
          "packageURL": "pkg:otp/hex?repository_url=https:%2F%2Fgithub.com%2Fhexpm%2Fhex\u0026vcs_url=repository_url=git%2Bhttps:%2F%2Fgithub.com%2Fhexpm%2Fhex.git",
          "product": "hex",
          "programFiles": [
            "src/mix_hex_repo.erl",
            "src/mix_hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "mix_hex_repo:get_names/1"
            },
            {
              "name": "mix_hex_repo:get_versions/1"
            },
            {
              "name": "mix_hex_repo:get_package/2"
            },
            {
              "name": "mix_hex_repo:get_policy/2"
            },
            {
              "name": "mix_hex_api:request/4"
            }
          ],
          "repo": "https://github.com/hexpm/hex",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "2.5.2",
              "status": "affected",
              "version": "2.1.0",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "mix_hex_repo",
            "mix_hex_api"
          ],
          "packageName": "hexpm/hex",
          "packageURL": "pkg:github/hexpm/hex",
          "product": "hex",
          "programFiles": [
            "src/mix_hex_repo.erl",
            "src/mix_hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "mix_hex_repo:get_names/1"
            },
            {
              "name": "mix_hex_repo:get_versions/1"
            },
            {
              "name": "mix_hex_repo:get_package/2"
            },
            {
              "name": "mix_hex_repo:get_policy/2"
            },
            {
              "name": "mix_hex_api:request/4"
            }
          ],
          "repo": "https://github.com/hexpm/hex",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "d8b60eee97abb119d525306f048969a217d793a5",
              "status": "affected",
              "version": "671f695ac548ed01f5828c2a739ecaa942b21007",
              "versionType": "git"
            }
          ]
        }
      ],
      "configurations": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eRegistry decoding is affected when a repository\u0027s URL points at a mirror or another server the user doesn\u0027t trust with the availability of their builds, for example Hex\u0027s \u003ccode\u003eHEX_MIRROR_URL\u003c/code\u003e or \u003ccode\u003emirror_url\u003c/code\u003e and rebar3\u0027s \u003ccode\u003eHEX_MIRROR_URL\u003c/code\u003e. API decoding is affected when the API URL points at such a server or an attacker can alter API responses. Requests to repo.hex.pm and hex.pm over verified HTTPS aren\u0027t affected.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Registry decoding is affected when a repository\u0027s URL points at a mirror or another server the user doesn\u0027t trust with the availability of their builds, for example Hex\u0027s `HEX_MIRROR_URL` or `mirror_url` and rebar3\u0027s `HEX_MIRROR_URL`. API decoding is affected when the API URL points at such a server or an attacker can alter API responses. Requests to repo.hex.pm and hex.pm over verified HTTPS aren\u0027t affected."
            }
          ],
          "value": "Registry decoding is affected when a repository\u0027s URL points at a mirror or another server the user doesn\u0027t trust with the availability of their builds, for example Hex\u0027s HEX_MIRROR_URL or mirror_url and rebar3\u0027s HEX_MIRROR_URL. API decoding is affected when the API URL points at such a server or an attacker can alter API responses. Requests to repo.hex.pm and hex.pm over verified HTTPS aren\u0027t affected."
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "3.27.3",
                  "versionStartIncluding": "3.9.1",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "0.20.0",
                  "versionStartIncluding": "0.1.0",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "2.5.2",
                  "versionStartIncluding": "2.1.0",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ],
          "operator": "AND"
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Peter Ullrich"
        },
        {
          "lang": "en",
          "type": "remediation developer",
          "value": "Eric Meadows-J\u00f6nsson"
        },
        {
          "lang": "en",
          "type": "analyst",
          "value": "Jonatan M\u00e4nnchen / EEF"
        }
      ],
      "dateAssigned": "2026-10-10T13:01:00.000Z",
      "datePublic": "2026-10-12T16:43:59.000Z",
      "descriptions": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eImproper Handling of Highly Compressed Data (Data Amplification) vulnerability in hexpm hex_core allows an untrusted repository mirror, or a server answering hex_core\u0027s API requests, to exhaust the memory of the Erlang VM running hex_core. The same code is vendored in Hex (\u003ccode\u003emix_hex_repo\u003c/code\u003e, \u003ccode\u003emix_hex_api\u003c/code\u003e) and rebar3 (\u003ccode\u003er3_hex_repo\u003c/code\u003e, \u003ccode\u003er3_hex_api\u003c/code\u003e).\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ehex_repo:get_names/1\u003c/code\u003e, \u003ccode\u003ehex_repo:get_versions/1\u003c/code\u003e, \u003ccode\u003ehex_repo:get_package/2\u003c/code\u003e and \u003ccode\u003ehex_repo:get_policy/2\u003c/code\u003e decompress the registry response with \u003ccode\u003ezlib:gunzip/1\u003c/code\u003e and decode the signed envelope before verifying its signature. A mirror doesn\u0027t have the repository\u0027s private key, but it chooses the compressed bytes, so a small response decompresses into an envelope of any size before the signature check rejects it.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ehex_api\u003c/code\u003e decodes responses with the \u003ccode\u003eapplication/vnd.hex+erlang\u003c/code\u003e content type through \u003ccode\u003ehex_safe_binary_to_term:safe_binary_to_term/1\u003c/code\u003e, which calls \u003ccode\u003ebinary_to_term(Binary, [safe])\u003c/code\u003e. The \u003ccode\u003esafe\u003c/code\u003e option prevents atom creation, but it accepts compressed terms and doesn\u0027t limit the size of the decoded term, and the check that rejects functions and ports runs after the term has been built. The fix for CVE-2026-21619 added the \u003ccode\u003esafe\u003c/code\u003e option and that check without bounding the decoded size.\u003c/p\u003e\n\u003cp\u003eThis issue affects rebar3: from 3.9.1 before 3.27.3; hex: from 2.1.0 before 2.5.2; hex_core: from 0.1.0 before 0.20.0.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in hexpm hex_core allows an untrusted repository mirror, or a server answering hex_core\u0027s API requests, to exhaust the memory of the Erlang VM running hex_core. The same code is vendored in Hex (`mix_hex_repo`, `mix_hex_api`) and rebar3 (`r3_hex_repo`, `r3_hex_api`).\n\n`hex_repo:get_names/1`, `hex_repo:get_versions/1`, `hex_repo:get_package/2` and `hex_repo:get_policy/2` decompress the registry response with `zlib:gunzip/1` and decode the signed envelope before verifying its signature. A mirror doesn\u0027t have the repository\u0027s private key, but it chooses the compressed bytes, so a small response decompresses into an envelope of any size before the signature check rejects it.\n\n`hex_api` decodes responses with the `application/vnd.hex+erlang` content type through `hex_safe_binary_to_term:safe_binary_to_term/1`, which calls `binary_to_term(Binary, [safe])`. The `safe` option prevents atom creation, but it accepts compressed terms and doesn\u0027t limit the size of the decoded term, and the check that rejects functions and ports runs after the term has been built. The fix for CVE-2026-21619 added the `safe` option and that check without bounding the decoded size.\n\nThis issue affects rebar3: from 3.9.1 before 3.27.3; hex: from 2.1.0 before 2.5.2; hex_core: from 0.1.0 before 0.20.0."
            }
          ],
          "value": "Improper Handling of Highly Compressed Data (Data Amplification) vulnerability in hexpm hex_core allows an untrusted repository mirror, or a server answering hex_core\u0027s API requests, to exhaust the memory of the Erlang VM running hex_core. The same code is vendored in Hex (mix_hex_repo, mix_hex_api) and rebar3 (r3_hex_repo, r3_hex_api).\n\nhex_repo:get_names/1, hex_repo:get_versions/1, hex_repo:get_package/2 and hex_repo:get_policy/2 decompress the registry response with zlib:gunzip/1 and decode the signed envelope before verifying its signature. A mirror doesn\u0027t have the repository\u0027s private key, but it chooses the compressed bytes, so a small response decompresses into an envelope of any size before the signature check rejects it.\n\nhex_api decodes responses with the application/vnd.hex+erlang content type through hex_safe_binary_to_term:safe_binary_to_term/1, which calls binary_to_term(Binary, [safe]). The safe option prevents atom creation, but it accepts compressed terms and doesn\u0027t limit the size of the decoded term, and the check that rejects functions and ports runs after the term has been built. The fix for CVE-2026-21619 added the safe option and that check without bounding the decoded size.\n\nThis issue affects rebar3: from 3.9.1 before 3.27.3; hex: from 2.1.0 before 2.5.2; hex_core: from 0.1.0 before 0.20.0."
        }
      ],
      "impacts": [
        {
          "capecId": "CAPEC-130",
          "descriptions": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eA mirror can make every registry fetch allocate memory far beyond the size of its response: in a test against Hex main 851b938, which vendors this code, a 65 KB registry response decompressed into a 64 MiB envelope before the signature check failed. The API server, or an attacker who can alter its responses, can do the same with API responses: 8 KB of compressed Erlang term format decoded into a list of 4.2 million elements. Large enough responses stop the Erlang VM, which fails the build tool command or the program using hex_core. No package code has to run.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "A mirror can make every registry fetch allocate memory far beyond the size of its response: in a test against Hex main 851b938, which vendors this code, a 65 KB registry response decompressed into a 64 MiB envelope before the signature check failed. The API server, or an attacker who can alter its responses, can do the same with API responses: 8 KB of compressed Erlang term format decoded into a list of 4.2 million elements. Large enough responses stop the Erlang VM, which fails the build tool command or the program using hex_core. No package code has to run."
                }
              ],
              "value": "A mirror can make every registry fetch allocate memory far beyond the size of its response: in a test against Hex main 851b938, which vendors this code, a 65 KB registry response decompressed into a 64 MiB envelope before the signature check failed. The API server, or an attacker who can alter its responses, can do the same with API responses: 8 KB of compressed Erlang term format decoded into a list of 4.2 million elements. Large enough responses stop the Erlang VM, which fails the build tool command or the program using hex_core. No package code has to run."
            }
          ]
        }
      ],
      "metrics": [
        {
          "cvssV4_0": {
            "Automatable": "NOT_DEFINED",
            "Recovery": "NOT_DEFINED",
            "Safety": "NOT_DEFINED",
            "attackComplexity": "LOW",
            "attackRequirements": "PRESENT",
            "attackVector": "NETWORK",
            "baseScore": 2.1,
            "baseSeverity": "LOW",
            "privilegesRequired": "NONE",
            "providerUrgency": "NOT_DEFINED",
            "subAvailabilityImpact": "NONE",
            "subConfidentialityImpact": "NONE",
            "subIntegrityImpact": "NONE",
            "userInteraction": "ACTIVE",
            "valueDensity": "NOT_DEFINED",
            "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N",
            "version": "4.0",
            "vulnAvailabilityImpact": "LOW",
            "vulnConfidentialityImpact": "NONE",
            "vulnIntegrityImpact": "NONE",
            "vulnerabilityResponseEffort": "NOT_DEFINED"
          },
          "format": "CVSS",
          "scenarios": [
            {
              "lang": "en",
              "value": "GENERAL"
            }
          ]
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-409",
              "description": "CWE-409 Improper Handling of Highly Compressed Data (Data Amplification)",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-10-12T18:16:57.155Z",
        "orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "shortName": "EEF"
      },
      "references": [
        {
          "name": "GitHub Advisory",
          "tags": [
            "related",
            "vendor-advisory"
          ],
          "url": "https://github.com/hexpm/hex_core/security/advisories/GHSA-7c4r-cgf9-9jmq"
        },
        {
          "name": "EEF CNA record for CVE-2026-105274",
          "tags": [
            "related"
          ],
          "url": "https://cna.erlef.org/cves/CVE-2026-105274.html"
        },
        {
          "name": "OSV record EEF-CVE-2026-105274",
          "tags": [
            "related"
          ],
          "url": "https://osv.dev/vulnerability/EEF-CVE-2026-105274"
        },
        {
          "name": "Introducing commit 209c02e in erlang/rebar3",
          "tags": [
            "related"
          ],
          "url": "https://github.com/erlang/rebar3/commit/209c02ec57c2cc3207ee0174c3af3675b8dc8f79"
        },
        {
          "name": "Fix commit 360838a in erlang/rebar3",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/erlang/rebar3/commit/360838a22f5b3a88c0358207f2923059bcbb3afb"
        },
        {
          "name": "Introducing commit fbb6d9d in hexpm/hex_core",
          "tags": [
            "related"
          ],
          "url": "https://github.com/hexpm/hex_core/commit/fbb6d9de472e5edb8d6fb6b32a91cb266137892e"
        },
        {
          "name": "Fix commit ebe25d1 in hexpm/hex_core",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/hexpm/hex_core/commit/ebe25d110717f6a3addba5232cd4a7dc1c76b628"
        },
        {
          "name": "Introducing commit 671f695 in hexpm/hex",
          "tags": [
            "related"
          ],
          "url": "https://github.com/hexpm/hex/commit/671f695ac548ed01f5828c2a739ecaa942b21007"
        },
        {
          "name": "Fix commit d8b60ee in hexpm/hex",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/hexpm/hex/commit/d8b60eee97abb119d525306f048969a217d793a5"
        }
      ],
      "solutions": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eUpgrade hex_core to 0.20.0 or later. Registry resources larger than 16 MiB after decompression are rejected with \u003ccode\u003e{too_big_uncompressed, MaxSize}\u003c/code\u003e, configurable with \u003ccode\u003eregistry_max_uncompressed_size\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eUpgrade Hex to 2.5.2 or later, which vendors hex_core 0.20.0. No rebar3 release vendors hex_core 0.20.0 yet.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Upgrade hex_core to 0.20.0 or later. Registry resources larger than 16 MiB after decompression are rejected with `{too_big_uncompressed, MaxSize}`, configurable with `registry_max_uncompressed_size`.\n\nUpgrade Hex to 2.5.2 or later, which vendors hex_core 0.20.0. No rebar3 release vendors hex_core 0.20.0 yet."
            }
          ],
          "value": "Upgrade hex_core to 0.20.0 or later. Registry resources larger than 16 MiB after decompression are rejected with {too_big_uncompressed, MaxSize}, configurable with registry_max_uncompressed_size.\n\nUpgrade Hex to 2.5.2 or later, which vendors hex_core 0.20.0. No rebar3 release vendors hex_core 0.20.0 yet."
        }
      ],
      "source": {
        "discovery": "UNKNOWN"
      },
      "title": "hex_core decompresses registry and Erlang term API responses without size limits",
      "workarounds": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003ePoint repository URLs at repo.hex.pm or a mirror you operate, and the API URL at hex.pm.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Point repository URLs at repo.hex.pm or a mirror you operate, and the API URL at hex.pm."
            }
          ],
          "value": "Point repository URLs at repo.hex.pm or a mirror you operate, and the API URL at hex.pm."
        }
      ],
      "x_proofOfConcept": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003col\u003e\n\u003cli\u003ePoint a repository at a loopback mirror (in Hex, \u003ccode\u003eHEX_MIRROR_URL\u003c/code\u003e) that answers \u003ccode\u003e/packages/probe\u003c/code\u003e with a 65,268-byte gzip stream decompressing to a 67,108,872-byte signed envelope with a 64 MiB payload and a one-byte signature.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eHex.Repo.get_package(\"hexpm\", \"probe\", nil)\u003c/code\u003e, which calls the vendored \u003ccode\u003ehex_repo:get_package/2\u003c/code\u003e, returns \u003ccode\u003e{:error, :bad_signature}\u003c/code\u003e after allocating the envelope. Peak RSS was 234 MiB, against 96 MiB for a 1,030-byte invalid envelope.\u003c/li\u003e\n\u003cli\u003eAnswer an API request with \u003ccode\u003econtent-type: application/vnd.hex+erlang\u003c/code\u003e and 8,178 bytes of compressed Erlang term format encoding a list of 4,194,304 elements. \u003ccode\u003emix_hex_api:get/2\u003c/code\u003e accepts the decoded term, and BEAM memory rises from 58 MiB to 272 MiB.\u003c/li\u003e\n\u003c/ol\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "1. Point a repository at a loopback mirror (in Hex, `HEX_MIRROR_URL`) that answers `/packages/probe` with a 65,268-byte gzip stream decompressing to a 67,108,872-byte signed envelope with a 64 MiB payload and a one-byte signature.\n2. `Hex.Repo.get_package(\"hexpm\", \"probe\", nil)`, which calls the vendored `hex_repo:get_package/2`, returns `{:error, :bad_signature}` after allocating the envelope. Peak RSS was 234 MiB, against 96 MiB for a 1,030-byte invalid envelope.\n3. Answer an API request with `content-type: application/vnd.hex+erlang` and 8,178 bytes of compressed Erlang term format encoding a list of 4,194,304 elements. `mix_hex_api:get/2` accepts the decoded term, and BEAM memory rises from 58 MiB to 272 MiB."
            }
          ],
          "value": "* Point a repository at a loopback mirror (in Hex, HEX_MIRROR_URL) that answers /packages/probe with a 65,268-byte gzip stream decompressing to a 67,108,872-byte signed envelope with a 64 MiB payload and a one-byte signature.\n* Hex.Repo.get_package(\"hexpm\", \"probe\", nil), which calls the vendored hex_repo:get_package/2, returns {:error, :bad_signature} after allocating the envelope. Peak RSS was 234 MiB, against 96 MiB for a 1,030-byte invalid envelope.\n* Answer an API request with content-type: application/vnd.hex+erlang and 8,178 bytes of compressed Erlang term format encoding a list of 4,194,304 elements. mix_hex_api:get/2 accepts the decoded term, and BEAM memory rises from 58 MiB to 272 MiB."
        }
      ],
      "x_technicalAnalysis": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003col\u003e\n\u003cli\u003e\u003ccode\u003ehex_repo:get_protobuf/3\u003c/code\u003e, used by \u003ccode\u003eget_names/1\u003c/code\u003e, \u003ccode\u003eget_versions/1\u003c/code\u003e, \u003ccode\u003eget_package/2\u003c/code\u003e and \u003ccode\u003eget_policy/2\u003c/code\u003e, calls \u003ccode\u003ezlib:gunzip/1\u003c/code\u003e on the whole response body with no output limit.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ehex_repo:decode/4\u003c/code\u003e then calls \u003ccode\u003ehex_registry:decode_and_verify_signed/2\u003c/code\u003e, which decodes the protobuf envelope, copying its payload and signature, before checking the signature.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ehex_api:request/4\u003c/code\u003e passes every response whose content type contains \u003ccode\u003eapplication/vnd.hex+erlang\u003c/code\u003e to \u003ccode\u003ehex_safe_binary_to_term:safe_binary_to_term/1\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esafe_binary_to_term/1\u003c/code\u003e calls \u003ccode\u003ebinary_to_term(Binary, [safe])\u003c/code\u003e, which decompresses compressed terms and builds the whole term, and only then walks it to reject functions and ports.\u003c/li\u003e\n\u003c/ol\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "1. `hex_repo:get_protobuf/3`, used by `get_names/1`, `get_versions/1`, `get_package/2` and `get_policy/2`, calls `zlib:gunzip/1` on the whole response body with no output limit.\n2. `hex_repo:decode/4` then calls `hex_registry:decode_and_verify_signed/2`, which decodes the protobuf envelope, copying its payload and signature, before checking the signature.\n3. `hex_api:request/4` passes every response whose content type contains `application/vnd.hex+erlang` to `hex_safe_binary_to_term:safe_binary_to_term/1`.\n4. `safe_binary_to_term/1` calls `binary_to_term(Binary, [safe])`, which decompresses compressed terms and builds the whole term, and only then walks it to reject functions and ports."
            }
          ],
          "value": "* hex_repo:get_protobuf/3, used by get_names/1, get_versions/1, get_package/2 and get_policy/2, calls zlib:gunzip/1 on the whole response body with no output limit.\n* hex_repo:decode/4 then calls hex_registry:decode_and_verify_signed/2, which decodes the protobuf envelope, copying its payload and signature, before checking the signature.\n* hex_api:request/4 passes every response whose content type contains application/vnd.hex+erlang to hex_safe_binary_to_term:safe_binary_to_term/1.\n* safe_binary_to_term/1 calls binary_to_term(Binary, [safe]), which decompresses compressed terms and builds the whole term, and only then walks it to reject functions and ports."
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
    "assignerShortName": "EEF",
    "cveId": "CVE-2026-105274",
    "datePublished": "2026-10-12T16:43:58.730Z",
    "dateReserved": "2026-10-10T13:00:02.355Z",
    "dateUpdated": "2026-10-15T18:05:12.446Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

CVE-2026-103502 (GCVE-0-2026-103502)
Vulnerability from cvelistv5
Published
2026-10-12 13:15
Modified
2026-10-16 16:58
CWE
  • CWE-295 - Improper Certificate Validation
  • CWE-636 - Not Failing Securely ('Failing Open')
Summary
Improper Certificate Validation vulnerability in hexpm hex_core allows an attacker who can intercept HTTPS connections to impersonate hex.pm, repo.hex.pm or any other repository or API server to programs that use hex_core's default HTTP adapter on Erlang/OTP 24, or on OTP 25 when the operating system's CA certificates can't be loaded. hex_core:default_config/0 selects the built-in hex_http_httpc adapter. For an HTTPS request whose adapter config has no ssl option, hex_http_httpc:http_options/2 builds options that verify the server certificate against public_key:cacerts_get/0. When that call raises, the adapter prints a warning and sends the request without ssl options, so httpc uses the defaults of the ssl application, which before OTP 26 don't verify the server certificate. public_key:cacerts_get/0 doesn't exist on OTP 24, so every HTTPS request falls back there, and on OTP 25 it raises when no CA store is found. hex_core versions before 0.11.0 never set ssl options, so they don't verify the server certificate on OTP 25 and earlier whether or not a CA store is found. The fallback was intended and documented, but the documentation didn't make clear that it meant no certificate verification. Since hex_core 0.8.2 the README has warned that the built-in httpc adapter "has insecure default settings" and recommended other HTTP clients, and the adapter prints "using default ssl options which are insecure" on every request that falls back. hex_core 0.11.0 added certificate verification with the changelog entry "Use secure SSL defaults for OTP 25+". Neither the README nor the warning says that the server certificate isn't verified, the README doesn't say which OTP versions the warning applies to, and on OTP 25 without CA certificates the warning tells users to upgrade to OTP 25 or later, which they already run. This advisory is published so that users who took those notices as general advice know their HTTPS requests weren't authenticated. This issue affects hex_core: from 0.1.0 before 0.20.0.
Impacted products
Vendor Product Version
hexpm hex_core Version: 0.1.0   ≤
    cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex_core Version: fbb6d9de472e5edb8d6fb6b32a91cb266137892e
    cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*
Create a notification for this product.
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2026-103502",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-10-16T16:55:40.731433Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2026-10-16T16:58:36.248Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      }
    ],
    "cna": {
      "affected": [
        {
          "collectionURL": "https://repo.hex.pm",
          "cpes": [
            "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "hex_http_httpc"
          ],
          "packageName": "hex_core",
          "packageURL": "pkg:hex/hex_core",
          "product": "hex_core",
          "programFiles": [
            "src/hex_http_httpc.erl"
          ],
          "programRoutines": [
            {
              "name": "hex_http_httpc:request/5"
            },
            {
              "name": "hex_http_httpc:request_to_file/6"
            }
          ],
          "repo": "https://github.com/hexpm/hex_core",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "0.20.0",
              "status": "affected",
              "version": "0.1.0",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "hex_http_httpc"
          ],
          "packageName": "hexpm/hex_core",
          "packageURL": "pkg:github/hexpm/hex_core",
          "product": "hex_core",
          "programFiles": [
            "src/hex_http_httpc.erl"
          ],
          "programRoutines": [
            {
              "name": "hex_http_httpc:request/5"
            },
            {
              "name": "hex_http_httpc:request_to_file/6"
            }
          ],
          "repo": "https://github.com/hexpm/hex_core",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "b7b3a42defb4ed8e20a5c68a4412ce68a95b7938",
              "status": "affected",
              "version": "fbb6d9de472e5edb8d6fb6b32a91cb266137892e",
              "versionType": "git"
            }
          ]
        }
      ],
      "configurations": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eAffects programs that use the \u003ccode\u003ehex_http_httpc\u003c/code\u003e adapter, the default in \u003ccode\u003ehex_core:default_config/0\u003c/code\u003e, without an \u003ccode\u003essl\u003c/code\u003e option in the adapter\u0027s \u003ccode\u003ehttp_options\u003c/code\u003e, on OTP 24, or on OTP 25 when \u003ccode\u003epublic_key:cacerts_get/0\u003c/code\u003e fails. hex_core versions before 0.11.0 are affected on OTP 25 and earlier whether or not the CA certificates load. On OTP 26 and later the \u003ccode\u003essl\u003c/code\u003e defaults verify the server certificate. Hex and rebar3 vendor hex_core but configure their own HTTP adapters, so they aren\u0027t affected.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Affects programs that use the `hex_http_httpc` adapter, the default in `hex_core:default_config/0`, without an `ssl` option in the adapter\u0027s `http_options`, on OTP 24, or on OTP 25 when `public_key:cacerts_get/0` fails. hex_core versions before 0.11.0 are affected on OTP 25 and earlier whether or not the CA certificates load. On OTP 26 and later the `ssl` defaults verify the server certificate. Hex and rebar3 vendor hex_core but configure their own HTTP adapters, so they aren\u0027t affected."
            }
          ],
          "value": "Affects programs that use the hex_http_httpc adapter, the default in hex_core:default_config/0, without an ssl option in the adapter\u0027s http_options, on OTP 24, or on OTP 25 when public_key:cacerts_get/0 fails. hex_core versions before 0.11.0 are affected on OTP 25 and earlier whether or not the CA certificates load. On OTP 26 and later the ssl defaults verify the server certificate. Hex and rebar3 vendor hex_core but configure their own HTTP adapters, so they aren\u0027t affected."
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "0.20.0",
                  "versionStartIncluding": "0.1.0",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ],
          "operator": "AND"
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Peter Ullrich"
        },
        {
          "lang": "en",
          "type": "remediation developer",
          "value": "Eric Meadows-J\u00f6nsson"
        },
        {
          "lang": "en",
          "type": "analyst",
          "value": "Jonatan M\u00e4nnchen / EEF"
        }
      ],
      "dateAssigned": "2026-10-10T12:59:18.000Z",
      "descriptions": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eImproper Certificate Validation vulnerability in hexpm hex_core allows an attacker who can intercept HTTPS connections to impersonate hex.pm, repo.hex.pm or any other repository or API server to programs that use hex_core\u0027s default HTTP adapter on Erlang/OTP 24, or on OTP 25 when the operating system\u0027s CA certificates can\u0027t be loaded.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ehex_core:default_config/0\u003c/code\u003e selects the built-in \u003ccode\u003ehex_http_httpc\u003c/code\u003e adapter. For an HTTPS request whose adapter config has no \u003ccode\u003essl\u003c/code\u003e option, \u003ccode\u003ehex_http_httpc:http_options/2\u003c/code\u003e builds options that verify the server certificate against \u003ccode\u003epublic_key:cacerts_get/0\u003c/code\u003e. When that call raises, the adapter prints a warning and sends the request without \u003ccode\u003essl\u003c/code\u003e options, so httpc uses the defaults of the \u003ccode\u003essl\u003c/code\u003e application, which before OTP 26 don\u0027t verify the server certificate. \u003ccode\u003epublic_key:cacerts_get/0\u003c/code\u003e doesn\u0027t exist on OTP 24, so every HTTPS request falls back there, and on OTP 25 it raises when no CA store is found. hex_core versions before 0.11.0 never set \u003ccode\u003essl\u003c/code\u003e options, so they don\u0027t verify the server certificate on OTP 25 and earlier whether or not a CA store is found.\u003c/p\u003e\n\u003cp\u003eThe fallback was intended and documented, but the documentation didn\u0027t make clear that it meant no certificate verification. Since hex_core 0.8.2 the README has warned that the built-in httpc adapter \"has insecure default settings\" and recommended other HTTP clients, and the adapter prints \"using default ssl options which are insecure\" on every request that falls back. hex_core 0.11.0 added certificate verification with the changelog entry \"Use secure SSL defaults for OTP 25+\". Neither the README nor the warning says that the server certificate isn\u0027t verified, the README doesn\u0027t say which OTP versions the warning applies to, and on OTP 25 without CA certificates the warning tells users to upgrade to OTP 25 or later, which they already run. This advisory is published so that users who took those notices as general advice know their HTTPS requests weren\u0027t authenticated.\u003c/p\u003e\n\u003cp\u003eThis issue affects hex_core: from 0.1.0 before 0.20.0.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Improper Certificate Validation vulnerability in hexpm hex_core allows an attacker who can intercept HTTPS connections to impersonate hex.pm, repo.hex.pm or any other repository or API server to programs that use hex_core\u0027s default HTTP adapter on Erlang/OTP 24, or on OTP 25 when the operating system\u0027s CA certificates can\u0027t be loaded.\n\n`hex_core:default_config/0` selects the built-in `hex_http_httpc` adapter. For an HTTPS request whose adapter config has no `ssl` option, `hex_http_httpc:http_options/2` builds options that verify the server certificate against `public_key:cacerts_get/0`. When that call raises, the adapter prints a warning and sends the request without `ssl` options, so httpc uses the defaults of the `ssl` application, which before OTP 26 don\u0027t verify the server certificate. `public_key:cacerts_get/0` doesn\u0027t exist on OTP 24, so every HTTPS request falls back there, and on OTP 25 it raises when no CA store is found. hex_core versions before 0.11.0 never set `ssl` options, so they don\u0027t verify the server certificate on OTP 25 and earlier whether or not a CA store is found.\n\nThe fallback was intended and documented, but the documentation didn\u0027t make clear that it meant no certificate verification. Since hex_core 0.8.2 the README has warned that the built-in httpc adapter \"has insecure default settings\" and recommended other HTTP clients, and the adapter prints \"using default ssl options which are insecure\" on every request that falls back. hex_core 0.11.0 added certificate verification with the changelog entry \"Use secure SSL defaults for OTP 25+\". Neither the README nor the warning says that the server certificate isn\u0027t verified, the README doesn\u0027t say which OTP versions the warning applies to, and on OTP 25 without CA certificates the warning tells users to upgrade to OTP 25 or later, which they already run. This advisory is published so that users who took those notices as general advice know their HTTPS requests weren\u0027t authenticated.\n\nThis issue affects hex_core: from 0.1.0 before 0.20.0."
            }
          ],
          "value": "Improper Certificate Validation vulnerability in hexpm hex_core allows an attacker who can intercept HTTPS connections to impersonate hex.pm, repo.hex.pm or any other repository or API server to programs that use hex_core\u0027s default HTTP adapter on Erlang/OTP 24, or on OTP 25 when the operating system\u0027s CA certificates can\u0027t be loaded.\n\nhex_core:default_config/0 selects the built-in hex_http_httpc adapter. For an HTTPS request whose adapter config has no ssl option, hex_http_httpc:http_options/2 builds options that verify the server certificate against public_key:cacerts_get/0. When that call raises, the adapter prints a warning and sends the request without ssl options, so httpc uses the defaults of the ssl application, which before OTP 26 don\u0027t verify the server certificate. public_key:cacerts_get/0 doesn\u0027t exist on OTP 24, so every HTTPS request falls back there, and on OTP 25 it raises when no CA store is found. hex_core versions before 0.11.0 never set ssl options, so they don\u0027t verify the server certificate on OTP 25 and earlier whether or not a CA store is found.\n\nThe fallback was intended and documented, but the documentation didn\u0027t make clear that it meant no certificate verification. Since hex_core 0.8.2 the README has warned that the built-in httpc adapter \"has insecure default settings\" and recommended other HTTP clients, and the adapter prints \"using default ssl options which are insecure\" on every request that falls back. hex_core 0.11.0 added certificate verification with the changelog entry \"Use secure SSL defaults for OTP 25+\". Neither the README nor the warning says that the server certificate isn\u0027t verified, the README doesn\u0027t say which OTP versions the warning applies to, and on OTP 25 without CA certificates the warning tells users to upgrade to OTP 25 or later, which they already run. This advisory is published so that users who took those notices as general advice know their HTTPS requests weren\u0027t authenticated.\n\nThis issue affects hex_core: from 0.1.0 before 0.20.0."
        }
      ],
      "impacts": [
        {
          "capecId": "CAPEC-94",
          "descriptions": [
            {
              "lang": "en",
              "supportingMedia": [
                {
                  "base64": false,
                  "type": "text/html",
                  "value": "\u003cp\u003eAn attacker on the network path between a program using hex_core\u0027s default adapter and a Hex repository or API server completes the TLS handshake with any certificate. It receives the API keys, OAuth tokens and repository keys the program sends, and can alter API requests and responses. Registry signatures, which hex_core verifies by default, still prevent changes to registry contents. Hex and rebar3 aren\u0027t affected because they configure their own HTTP adapters.\u003c/p\u003e"
                },
                {
                  "base64": false,
                  "type": "text/markdown",
                  "value": "An attacker on the network path between a program using hex_core\u0027s default adapter and a Hex repository or API server completes the TLS handshake with any certificate. It receives the API keys, OAuth tokens and repository keys the program sends, and can alter API requests and responses. Registry signatures, which hex_core verifies by default, still prevent changes to registry contents. Hex and rebar3 aren\u0027t affected because they configure their own HTTP adapters."
                }
              ],
              "value": "An attacker on the network path between a program using hex_core\u0027s default adapter and a Hex repository or API server completes the TLS handshake with any certificate. It receives the API keys, OAuth tokens and repository keys the program sends, and can alter API requests and responses. Registry signatures, which hex_core verifies by default, still prevent changes to registry contents. Hex and rebar3 aren\u0027t affected because they configure their own HTTP adapters."
            }
          ]
        }
      ],
      "metrics": [
        {
          "cvssV4_0": {
            "Automatable": "NOT_DEFINED",
            "Recovery": "NOT_DEFINED",
            "Safety": "NOT_DEFINED",
            "attackComplexity": "LOW",
            "attackRequirements": "PRESENT",
            "attackVector": "NETWORK",
            "baseScore": 5.9,
            "baseSeverity": "MEDIUM",
            "privilegesRequired": "NONE",
            "providerUrgency": "NOT_DEFINED",
            "subAvailabilityImpact": "NONE",
            "subConfidentialityImpact": "NONE",
            "subIntegrityImpact": "NONE",
            "userInteraction": "ACTIVE",
            "valueDensity": "NOT_DEFINED",
            "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N",
            "version": "4.0",
            "vulnAvailabilityImpact": "NONE",
            "vulnConfidentialityImpact": "HIGH",
            "vulnIntegrityImpact": "LOW",
            "vulnerabilityResponseEffort": "NOT_DEFINED"
          },
          "format": "CVSS",
          "scenarios": [
            {
              "lang": "en",
              "value": "GENERAL"
            }
          ]
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-295",
              "description": "CWE-295 Improper Certificate Validation",
              "lang": "en",
              "type": "CWE"
            }
          ]
        },
        {
          "descriptions": [
            {
              "cweId": "CWE-636",
              "description": "CWE-636 Not Failing Securely (\u0027Failing Open\u0027)",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-10-12T13:15:29.040Z",
        "orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "shortName": "EEF"
      },
      "references": [
        {
          "name": "GitHub Advisory",
          "tags": [
            "related",
            "vendor-advisory"
          ],
          "url": "https://github.com/hexpm/hex_core/security/advisories/GHSA-p26c-h8c2-rwqj"
        },
        {
          "name": "EEF CNA record for CVE-2026-103502",
          "tags": [
            "related"
          ],
          "url": "https://cna.erlef.org/cves/CVE-2026-103502.html"
        },
        {
          "name": "OSV record EEF-CVE-2026-103502",
          "tags": [
            "related"
          ],
          "url": "https://osv.dev/vulnerability/EEF-CVE-2026-103502"
        },
        {
          "name": "Introducing commit fbb6d9d in hexpm/hex_core",
          "tags": [
            "related"
          ],
          "url": "https://github.com/hexpm/hex_core/commit/fbb6d9de472e5edb8d6fb6b32a91cb266137892e"
        },
        {
          "name": "Fix commit b7b3a42 in hexpm/hex_core",
          "tags": [
            "patch"
          ],
          "url": "https://github.com/hexpm/hex_core/commit/b7b3a42defb4ed8e20a5c68a4412ce68a95b7938"
        }
      ],
      "solutions": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003eUpgrade hex_core to 0.20.0 or later. On OTP 24, or on OTP 25 without the operating system\u0027s CA certificates, HTTPS requests through \u003ccode\u003ehex_http_httpc\u003c/code\u003e then fail with \u003ccode\u003e{error, {cacerts_unavailable, Reason}}\u003c/code\u003e unless the adapter config has \u003ccode\u003essl\u003c/code\u003e options.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Upgrade hex_core to 0.20.0 or later. On OTP 24, or on OTP 25 without the operating system\u0027s CA certificates, HTTPS requests through `hex_http_httpc` then fail with `{error, {cacerts_unavailable, Reason}}` unless the adapter config has `ssl` options."
            }
          ],
          "value": "Upgrade hex_core to 0.20.0 or later. On OTP 24, or on OTP 25 without the operating system\u0027s CA certificates, HTTPS requests through hex_http_httpc then fail with {error, {cacerts_unavailable, Reason}} unless the adapter config has ssl options."
        }
      ],
      "source": {
        "discovery": "UNKNOWN"
      },
      "title": "hex_core\u0027s default HTTP adapter doesn\u0027t verify TLS certificates on OTP 24 and 25",
      "workarounds": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003cp\u003ePass \u003ccode\u003essl\u003c/code\u003e options that verify the server certificate in the adapter config, for example \u003ccode\u003e{hex_http_httpc, #{http_options =\u0026gt; [{ssl, SslOpts}]}}\u003c/code\u003e, use another HTTP adapter, or run on OTP 26 or later.\u003c/p\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "Pass `ssl` options that verify the server certificate in the adapter config, for example `{hex_http_httpc, #{http_options =\u003e [{ssl, SslOpts}]}}`, use another HTTP adapter, or run on OTP 26 or later."
            }
          ],
          "value": "Pass ssl options that verify the server certificate in the adapter config, for example {hex_http_httpc, #{http_options =\u003e [{ssl, SslOpts}]}}, use another HTTP adapter, or run on OTP 26 or later."
        }
      ],
      "x_proofOfConcept": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003col\u003e\n\u003cli\u003eCompile \u003ccode\u003esrc/hex_http.erl\u003c/code\u003e and \u003ccode\u003esrc/hex_http_httpc.erl\u003c/code\u003e from hex_core main 4fbc5d1 in the \u003ccode\u003eerlang:24\u003c/code\u003e Docker image and run \u003ccode\u003ehex_http_httpc:request(get, \u0026lt;\u0026lt;\"https://self-signed.badssl.com/\"\u0026gt;\u0026gt;, #{}, undefined, #{profile =\u0026gt; default})\u003c/code\u003e after starting inets and ssl.\u003c/li\u003e\n\u003cli\u003eThe adapter prints \u003ccode\u003e[hex_http_httpc] using default ssl options which are insecure.\u003c/code\u003e and returns \u003ccode\u003e{ok, {200, Headers, Body}}\u003c/code\u003e from the server with the self-signed certificate.\u003c/li\u003e\n\u003cli\u003eIn the \u003ccode\u003eerlang:25\u003c/code\u003e image with an empty tmpfs mounted on \u003ccode\u003e/etc/ssl/certs\u003c/code\u003e, \u003ccode\u003epublic_key:cacerts_get/0\u003c/code\u003e raises and the request also returns \u003ccode\u003e{ok, {200, ...}}\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eIn the \u003ccode\u003eerlang:25\u003c/code\u003e image with the CA store present (150 certificates), the same request fails with \u003ccode\u003e{error, {failed_connect, ...}}\u003c/code\u003e after a \u003ccode\u003eBad Certificate\u003c/code\u003e alert.\u003c/li\u003e\n\u003c/ol\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "1. Compile `src/hex_http.erl` and `src/hex_http_httpc.erl` from hex_core main 4fbc5d1 in the `erlang:24` Docker image and run `hex_http_httpc:request(get, \u003c\u003c\"https://self-signed.badssl.com/\"\u003e\u003e, #{}, undefined, #{profile =\u003e default})` after starting inets and ssl.\n2. The adapter prints `[hex_http_httpc] using default ssl options which are insecure.` and returns `{ok, {200, Headers, Body}}` from the server with the self-signed certificate.\n3. In the `erlang:25` image with an empty tmpfs mounted on `/etc/ssl/certs`, `public_key:cacerts_get/0` raises and the request also returns `{ok, {200, ...}}`.\n4. In the `erlang:25` image with the CA store present (150 certificates), the same request fails with `{error, {failed_connect, ...}}` after a `Bad Certificate` alert."
            }
          ],
          "value": "* Compile src/hex_http.erl and src/hex_http_httpc.erl from hex_core main 4fbc5d1 in the erlang:24 Docker image and run hex_http_httpc:request(get, \u003c\u003c\"https://self-signed.badssl.com/\"\u003e\u003e, #{}, undefined, #{profile =\u003e default}) after starting inets and ssl.\n* The adapter prints [hex_http_httpc] using default ssl options which are insecure. and returns {ok, {200, Headers, Body}} from the server with the self-signed certificate.\n* In the erlang:25 image with an empty tmpfs mounted on /etc/ssl/certs, public_key:cacerts_get/0 raises and the request also returns {ok, {200, ...}}.\n* In the erlang:25 image with the CA store present (150 certificates), the same request fails with {error, {failed_connect, ...}} after a Bad Certificate alert."
        }
      ],
      "x_technicalAnalysis": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "\u003col\u003e\n\u003cli\u003e\u003ccode\u003ehex_core:default_config/0\u003c/code\u003e sets \u003ccode\u003ehttp_adapter\u003c/code\u003e to \u003ccode\u003e{hex_http_httpc, #{profile =\u0026gt; default}}\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ehex_http_httpc:request/5\u003c/code\u003e and \u003ccode\u003ehex_http_httpc:request_to_file/6\u003c/code\u003e build their httpc options with \u003ccode\u003ehttp_options/2\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eFor an \u003ccode\u003ehttps\u003c/code\u003e URI whose adapter config has no \u003ccode\u003essl\u003c/code\u003e entry in \u003ccode\u003ehttp_options\u003c/code\u003e, \u003ccode\u003ehttp_options/2\u003c/code\u003e adds \u003ccode\u003e{ssl, [{verify, verify_peer}, {cacerts, public_key:cacerts_get()}, ...]}\u003c/code\u003e inside a \u003ccode\u003etry\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eWhen \u003ccode\u003epublic_key:cacerts_get/0\u003c/code\u003e raises (\u003ccode\u003eundef\u003c/code\u003e on OTP 24; an error on OTP 25 when no CA store is found), the \u003ccode\u003ecatch\u003c/code\u003e prints a warning with \u003ccode\u003eio:format/1\u003c/code\u003e and returns the options without \u003ccode\u003essl\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003ehttpc then uses the \u003ccode\u003essl\u003c/code\u003e application\u0027s defaults, which are \u003ccode\u003everify_none\u003c/code\u003e before OTP 26, and completes the handshake with any certificate.\u003c/li\u003e\n\u003cli\u003ehex_core before 0.11.0 (e57b4fb) had no step 3: it never passed \u003ccode\u003essl\u003c/code\u003e options, so step 5 applied on every OTP version before 26.\u003c/li\u003e\n\u003c/ol\u003e"
            },
            {
              "base64": false,
              "type": "text/markdown",
              "value": "1. `hex_core:default_config/0` sets `http_adapter` to `{hex_http_httpc, #{profile =\u003e default}}`.\n2. `hex_http_httpc:request/5` and `hex_http_httpc:request_to_file/6` build their httpc options with `http_options/2`.\n3. For an `https` URI whose adapter config has no `ssl` entry in `http_options`, `http_options/2` adds `{ssl, [{verify, verify_peer}, {cacerts, public_key:cacerts_get()}, ...]}` inside a `try`.\n4. When `public_key:cacerts_get/0` raises (`undef` on OTP 24; an error on OTP 25 when no CA store is found), the `catch` prints a warning with `io:format/1` and returns the options without `ssl`.\n5. httpc then uses the `ssl` application\u0027s defaults, which are `verify_none` before OTP 26, and completes the handshake with any certificate.\n6. hex_core before 0.11.0 (e57b4fb) had no step 3: it never passed `ssl` options, so step 5 applied on every OTP version before 26."
            }
          ],
          "value": "* hex_core:default_config/0 sets http_adapter to {hex_http_httpc, #{profile =\u003e default}}.\n* hex_http_httpc:request/5 and hex_http_httpc:request_to_file/6 build their httpc options with http_options/2.\n* For an https URI whose adapter config has no ssl entry in http_options, http_options/2 adds {ssl, [{verify, verify_peer}, {cacerts, public_key:cacerts_get()}, ...]} inside a try.\n* When public_key:cacerts_get/0 raises (undef on OTP 24; an error on OTP 25 when no CA store is found), the catch prints a warning with io:format/1 and returns the options without ssl.\n* httpc then uses the ssl application\u0027s defaults, which are verify_none before OTP 26, and completes the handshake with any certificate.\n* hex_core before 0.11.0 (e57b4fb) had no step 3: it never passed ssl options, so step 5 applied on every OTP version before 26."
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
    "assignerShortName": "EEF",
    "cveId": "CVE-2026-103502",
    "datePublished": "2026-10-12T13:15:29.040Z",
    "dateReserved": "2026-10-09T16:45:02.344Z",
    "dateUpdated": "2026-10-16T16:58:36.248Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

CVE-2026-21619 (GCVE-0-2026-21619)
Vulnerability from cvelistv5
Published
2026-02-27 17:57
Modified
2026-05-27 15:40
CWE
  • CWE-400 - Uncontrolled Resource Consumption
  • CWE-502 - Deserialization of Untrusted Data
Summary
Uncontrolled Resource Consumption, Deserialization of Untrusted Data vulnerability in hexpm hex_core (hex_api modules), hexpm hex (mix_hex_api modules), erlang rebar3 (r3_hex_api modules) allows Object Injection, Excessive Allocation. This vulnerability is associated with program files src/hex_api.erl, src/mix_hex_api.erl, apps/rebar/src/vendored/r3_hex_api.erl and program routines hex_core:request/4, mix_hex_api:request/4, r3_hex_api:request/4. This issue affects hex_core: from 0.1.0 before 0.12.1; hex: from 2.3.0 before 2.3.2; rebar3: from 3.9.1 before 3.27.0.
Impacted products
Vendor Product Version
hexpm hex_core Version: eb327f8edfe45507351e38cc0805aa12fa647f0b
    cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex_core Version: 0.1.0   ≤
    cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex Version: 314546ac432229518714cc8e3336e916b9da6305
    cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*
Create a notification for this product.
   hexpm hex Version: 2.3.0   ≤
    cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*
Create a notification for this product.
   erlang rebar3 Version: 209c02ec57c2cc3207ee0174c3af3675b8dc8f79
    cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*
Create a notification for this product.
   erlang rebar3 Version: 3.9.1   ≤
    cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*
Create a notification for this product.
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2026-21619",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-02-27T19:08:49.652728Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2026-02-27T19:08:57.019Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      }
    ],
    "cna": {
      "affected": [
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "hex_api"
          ],
          "packageName": "hexpm/hex_core",
          "packageURL": "pkg:github/hexpm/hex_core",
          "product": "hex_core",
          "programFiles": [
            "src/hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "hex_core:request/4"
            }
          ],
          "repo": "https://github.com/hexpm/hex_core",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "cdf726095bca85ad2549d146df1e831ae93c2b13",
              "status": "affected",
              "version": "eb327f8edfe45507351e38cc0805aa12fa647f0b",
              "versionType": "git"
            }
          ]
        },
        {
          "collectionURL": "https://repo.hex.pm",
          "cpes": [
            "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "hex_api"
          ],
          "packageName": "hex_core",
          "packageURL": "pkg:hex/hex_core",
          "product": "hex_core",
          "programFiles": [
            "src/hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "hex_core:request/4"
            }
          ],
          "repo": "https://github.com/hexpm/hex_core",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "0.12.1",
              "status": "affected",
              "version": "0.1.0",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "mix_hex_api"
          ],
          "packageName": "hexpm/hex",
          "packageURL": "pkg:github/hexpm/hex",
          "product": "hex",
          "programFiles": [
            "src/mix_hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "mix_hex_api:request/4"
            }
          ],
          "repo": "https://github.com/hexpm/hex",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "636739f3322514e9303ca335fb630696fcbb3c95",
              "status": "affected",
              "version": "314546ac432229518714cc8e3336e916b9da6305",
              "versionType": "git"
            }
          ]
        },
        {
          "cpes": [
            "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "mix_hex_api"
          ],
          "packageName": "hex",
          "packageURL": "pkg:otp/hex?repository_url=https:%2F%2Fgithub.com%2Fhexpm%2Fhex.git\u0026vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Fhexpm%2Fhex.git",
          "product": "hex",
          "programFiles": [
            "src/mix_hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "mix_hex_api:request/4"
            }
          ],
          "repo": "https://github.com/hexpm/hex",
          "vendor": "hexpm",
          "versions": [
            {
              "lessThan": "2.3.2",
              "status": "affected",
              "version": "2.3.0",
              "versionType": "semver"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "r3_hex_api"
          ],
          "packageName": "erlang/rebar3",
          "packageURL": "pkg:github/erlang/rebar3",
          "product": "rebar3",
          "programFiles": [
            "apps/rebar/src/vendored/r3_hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "r3_hex_api:request/4"
            }
          ],
          "repo": "https://github.com/erlang/rebar3",
          "vendor": "erlang",
          "versions": [
            {
              "lessThan": "1d4478f527e373de0b225951e53115450e0d9b9d",
              "status": "affected",
              "version": "209c02ec57c2cc3207ee0174c3af3675b8dc8f79",
              "versionType": "git"
            }
          ]
        },
        {
          "collectionURL": "https://github.com",
          "cpes": [
            "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*"
          ],
          "defaultStatus": "unaffected",
          "modules": [
            "r3_hex_api"
          ],
          "packageName": "rebar3",
          "packageURL": "pkg:otp/rebar3?repository_url=https:%2F%2Fgithub.com%2Ferlang%2Frebar3.git\u0026vcs_url=git%2Bhttps:%2F%2Fgithub.com%2Ferlang%2Frebar3.git",
          "product": "rebar3",
          "programFiles": [
            "apps/rebar/src/vendored/r3_hex_api.erl"
          ],
          "programRoutines": [
            {
              "name": "r3_hex_api:request/4"
            }
          ],
          "repo": "https://github.com/erlang/rebar3",
          "vendor": "erlang",
          "versions": [
            {
              "lessThan": "3.27.0",
              "status": "affected",
              "version": "3.9.1",
              "versionType": "semver"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:a:hexpm:hex_core:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "0.12.1",
                  "versionStartIncluding": "0.1.0",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "AND"
            },
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:a:hexpm:hex:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "2.3.2",
                  "versionStartIncluding": "2.3.0",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "AND"
            },
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:a:erlang:rebar3:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "3.27.0",
                  "versionStartIncluding": "3.9.1",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "AND"
            }
          ],
          "operator": "OR"
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Michael Lubas / Paraxial.io"
        },
        {
          "lang": "en",
          "type": "remediation developer",
          "value": "Jonatan M\u00e4nnchen / EEF"
        },
        {
          "lang": "en",
          "type": "remediation reviewer",
          "value": "Eric Meadows-J\u00f6nsson / Hex.pm"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "supportingMedia": [
            {
              "base64": false,
              "type": "text/html",
              "value": "Uncontrolled Resource Consumption, Deserialization of Untrusted Data vulnerability in hexpm hex_core (hex_api modules), hexpm hex (mix_hex_api modules), erlang rebar3 (r3_hex_api modules) allows Object Injection, Excessive Allocation.\u003cp\u003e This vulnerability is associated with program files \u003ctt\u003esrc/hex_api.erl\u003c/tt\u003e, \u003ctt\u003esrc/mix_hex_api.erl\u003c/tt\u003e, \u003ctt\u003eapps/rebar/src/vendored/r3_hex_api.erl\u003c/tt\u003e and program routines \u003ctt\u003ehex_core:request/4\u003c/tt\u003e, \u003ctt\u003emix_hex_api:request/4\u003c/tt\u003e, \u003ctt\u003er3_hex_api:request/4\u003c/tt\u003e.\u003c/p\u003e\u003cp\u003eThis issue affects hex_core: from 0.1.0 before 0.12.1; hex: from 2.3.0 before 2.3.2; rebar3: from 3.9.1 before 3.27.0.\u003c/p\u003e"
            }
          ],
          "value": "Uncontrolled Resource Consumption, Deserialization of Untrusted Data vulnerability in hexpm hex_core (hex_api modules), hexpm hex (mix_hex_api modules), erlang rebar3 (r3_hex_api modules) allows Object Injection, Excessive Allocation. This vulnerability is associated with program files src/hex_api.erl, src/mix_hex_api.erl, apps/rebar/src/vendored/r3_hex_api.erl and program routines hex_core:request/4, mix_hex_api:request/4, r3_hex_api:request/4.\n\nThis issue affects hex_core: from 0.1.0 before 0.12.1; hex: from 2.3.0 before 2.3.2; rebar3: from 3.9.1 before 3.27.0."
        }
      ],
      "impacts": [
        {
          "capecId": "CAPEC-586",
          "descriptions": [
            {
              "lang": "en",
              "value": "CAPEC-586 Object Injection"
            }
          ]
        },
        {
          "capecId": "CAPEC-130",
          "descriptions": [
            {
              "lang": "en",
              "value": "CAPEC-130 Excessive Allocation"
            }
          ]
        }
      ],
      "metrics": [
        {
          "cvssV4_0": {
            "Automatable": "NOT_DEFINED",
            "Recovery": "NOT_DEFINED",
            "Safety": "NOT_DEFINED",
            "attackComplexity": "LOW",
            "attackRequirements": "PRESENT",
            "attackVector": "NETWORK",
            "baseScore": 2,
            "baseSeverity": "LOW",
            "exploitMaturity": "NOT_DEFINED",
            "privilegesRequired": "LOW",
            "providerUrgency": "NOT_DEFINED",
            "subAvailabilityImpact": "NONE",
            "subConfidentialityImpact": "NONE",
            "subIntegrityImpact": "NONE",
            "userInteraction": "ACTIVE",
            "valueDensity": "NOT_DEFINED",
            "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N",
            "version": "4.0",
            "vulnAvailabilityImpact": "LOW",
            "vulnConfidentialityImpact": "NONE",
            "vulnIntegrityImpact": "NONE",
            "vulnerabilityResponseEffort": "NOT_DEFINED"
          },
          "format": "CVSS",
          "scenarios": [
            {
              "lang": "en",
              "value": "GENERAL"
            }
          ]
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-400",
              "description": "CWE-400 Uncontrolled Resource Consumption",
              "lang": "en",
              "type": "CWE"
            }
          ]
        },
        {
          "descriptions": [
            {
              "cweId": "CWE-502",
              "description": "CWE-502 Deserialization of Untrusted Data",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-05-27T15:40:33.166Z",
        "orgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
        "shortName": "EEF"
      },
      "references": [
        {
          "tags": [
            "vendor-advisory",
            "related"
          ],
          "url": "https://github.com/hexpm/hex_core/security/advisories/GHSA-hx9w-f2w9-9g96"
        },
        {
          "tags": [
            "related"
          ],
          "url": "https://cna.erlef.org/cves/CVE-2026-21619.html"
        },
        {
          "tags": [
            "related"
          ],
          "url": "https://osv.dev/vulnerability/EEF-CVE-2026-21619"
        },
        {
          "tags": [
            "patch"
          ],
          "url": "https://github.com/hexpm/hex_core/commit/cdf726095bca85ad2549d146df1e831ae93c2b13"
        },
        {
          "tags": [
            "patch"
          ],
          "url": "https://github.com/hexpm/hex/commit/636739f3322514e9303ca335fb630696fcbb3c95"
        },
        {
          "tags": [
            "patch"
          ],
          "url": "https://github.com/erlang/rebar3/commit/1d4478f527e373de0b225951e53115450e0d9b9d"
        }
      ],
      "source": {
        "discovery": "INTERNAL"
      },
      "title": "Unsafe Deserialization of Erlang Terms in hex_core",
      "x_generator": {
        "engine": "Vulnogram 0.5.0"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "6b3ad84c-e1a6-4bf7-a703-f496b71e49db",
    "assignerShortName": "EEF",
    "cveId": "CVE-2026-21619",
    "datePublished": "2026-02-27T17:57:11.513Z",
    "dateReserved": "2026-01-01T03:46:45.933Z",
    "dateUpdated": "2026-05-27T15:40:33.166Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}