CVE-2026-40070: Bsv sdk Bsv-sdk And Bsv-wallet Persist Unverified Vulnerability

HIGH
Advisory Identifier: GHSA-hc36-c89j-5f4j
CVSS 8.1
CWE-347
Published
Advisory Summary

CVE-2026-40070 is a HIGH (CVSS 8.1) bsv-sdk and bsv-wallet persist unverified vulnerability (CWE-347: Improper Verification of Cryptographic Signature) affecting Bsv sdk libraries in the RubyGems ecosystem. The issue involves bsv-sdk and bsv-wallet persist unverified certifier signatures in acquire_certificate (direct and issuance paths). Remediation is available by upgrading affected packages to version 0.8.2, 0.3.4.

CVE-2026-40070 at a Glance

CVE Identifier CVE-2026-40070
GHSA Identifier GHSA-hc36-c89j-5f4j
Severity HIGH
CVSS v3.1 Base Score 8.1
CWE Classification CWE-347: Improper Verification of Cryptographic Signature
Affected Product Bsv sdk
Package Ecosystem RubyGems
Published Date
Last Updated

Security Impact

CVSS: 8.1

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

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

How to Fix CVE-2026-40070

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

bsv-sdk fixed: 0.8.2
Upgrade bsv-sdk to 0.8.2
bsv-wallet fixed: 0.3.4
Upgrade bsv-wallet to 0.3.4
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 bsv-sdk

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-40070, inspect your project dependencies for Bsv sdk:

inspect dependencies for bsv-sdk

Analyze the terminal output to locate any version of Bsv sdk in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.8.2), 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-347: Improper Verification of Cryptographic Signature, where the product does not verify, or incorrectly verifies, the cryptographic signature for data. In Bsv sdk, 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

# Unverified certifier signatures persisted by `acquire_certificate` ## Affected packages Both `bsv-sdk` and `bsv-wallet` are published from the [sgbett/bsv-ruby-sdk](https://github.com/sgbett/bsv-ruby-sdk) repository. The vulnerable code lives in `lib/bsv/wallet_interface/wallet_client.rb`, which is **physically shipped inside both gems** (the `bsv-wallet.gemspec` `files` list bundles the entire `lib/bsv/wallet_interface/` tree). Consumers of either gem are independently vulnerable; the two packages are versioned separately, so each has its own affected range. | Package | Affected | Patched | | --- | --- | --- | | `bsv-sdk` | `>= 0.3.1, < 0.8.2` | `0.8.2` | | `bsv-wallet` | `>= 0.1.2, < 0.3.4` | `0.3.4` | ## Summary `BSV::Wallet::WalletClient#acquire_certificate` persists certificate records to storage **without verifying the certifier's signature** over the certificate contents. Both acquisition paths are affected: - `acquisition_protocol: 'direct'` — the caller supplies all certificate fields (including `signature:`) and the record is written to storage verbatim. - `acquisition_protocol: 'issuance'` — the client POSTs to a certifier URL and writes whatever signature the response body contains, also without verification. An attacker who can reach either API (or who controls a certifier endpoint targeted by the issuance path) can forge identity certificates that subsequently appear authentic to `list_certificates` and `prove_certificate`. ## Details BRC-52 requires a certificate's `signature` field to be verified against the claimed certifier's public key over a canonical hashing of `(type, subject, serialNumber, revocationOutpoint, fields)` before the certificate is trusted. The reference TypeScript SDK enforces this in `Certificate.verify()`. ### Direct path The Ruby implementation's `acquire_via_direct` path (`lib/bsv/wallet_interface/wallet_client.rb`) constructs the certificate record directly from caller-supplied fields: ```ruby def acquire_via_direct(args) { type: args[:type], subject: @key_deriver.identity_key, serial_number: args[:serial_number], certifier: args[:certifier], revocation_outpoint: args[:revocation_outpoint], signature: args[:signature], fields: args[:fields], keyring: args[:keyring_for_subject] } end ``` The returned record is then written to the storage adapter by `acquire_certificate`. No verification of `args[:signature]` against `args[:certifier]`'s public key occurs at any point in this path. ### Issuance path `acquire_via_issuance` POSTs to a certifier-supplied URL and parses the response body into a certificate record, which is then written to storage without verifying the returned signature. A hostile or compromised certifier endpoint — or anyone able to redirect/MITM the plain HTTP request — can therefore return an arbitrary `signature` value for any subject and have it stored as authentic. This is the same class of bypass as the direct path; it was tracked separately as finding **F8.16** in the compliance review and is closed by the same fix. ### Downstream impact Downstream reads via `list_certificates` and selective-disclosure via `prove_certificate` treat stored records as valid without re-verifying, so any forgery that slips past `acquire_certificate` is trusted permanently. ## Impact Any caller that can invoke `acquire_certificate` — via either acquisition protocol — can forge a certificate attributed to an arbitrary certifier identity key, containing arbitrary fields, and have it persisted as authentic. Applications and downstream gems that rely on the wallet's certificate store as a source of truth for identity attributes (e.g. KYC assertions, role claims, attestations) are subject to credential forgery. This is a credential-forgery primitive, not merely a spec divergence from BRC-52. ## CVSS rationale `AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N` → **8.1 (High)** - **AV:N** — network-reachable in any wallet context that exposes `acquire_certificate` to callers. - **AC:L** — low attack complexity: pass arbitrary bytes as `signature:`. - **PR:L** — low privileges: any caller authorised to invoke `acquire_certificate`. - **UI:N** — no user interaction required. - **C:H** — forged credentials via `prove_certificate` can assert attributes about the subject. - **I:H** — the wallet's credential store is polluted with attacker-controlled data. - **A:N** — availability unaffected. ## Proof of concept ```ruby client = BSV::Wallet::WalletClient.new(key, storage: BSV::Wallet::MemoryStore.new) client.acquire_certificate( type: 'age-over-18', acquisition_protocol: 'direct', certifier: claimed_trusted_pubkey_hex, serial_number: 'any-serial', revocation_outpoint: ('00' * 32) + '.0', signature: 'deadbeef' * 16, # arbitrary bytes — never verified fields: { 'verified' => 'true' }, keyring_for_subject: {} ) client.list_certificates( certifiers: [claimed_trusted_pubkey_hex], types: ['age-over-18'] ) # => returns the forged record as if it were a real certificate from that certifier ``` ## Affected versions The vulnerable direct-path code was introduced in commit `d14dd19` ("feat(wallet): implement BRC-100 identity certificate methods (Phase 5)") on 2026-03-27 20:35 UTC. The vulnerable issuance-path code was added one day later in `6a4d898` ("feat(wallet): implement certificate issuance protocol", 2026-03-28 04:38 UTC), which removed an earlier `raise UnsupportedActionError` and replaced it with an unverified HTTP POST. **`bsv-sdk`:** the v0.3.1 chore bump (`89de3a2`) was committed 28 minutes after `d14dd19`, so the direct-path bypass shipped in the **v0.3.1** tag. The v0.3.1 release raised `UnsupportedActionError` for the issuance path, so the issuance-path bypass first shipped in **v0.3.2** (`5a335de`). Every subsequent release up to and including **v0.8.1** is affected by at least one path, and every release from v0.3.2 onwards is affected by both. Combined affected range: `>= 0.3.1, < 0.8.2`. **`bsv-wallet`:** at the time both commits landed, the wallet gem was at version 0.1.1. The first wallet release containing any of the vulnerable code was **v0.1.2** (`5a335de`, 2026-03-30), which shipped both paths simultaneously. Every subsequent release up to and including **v0.3.3** is affected on both paths. Affected range: `>= 0.1.2, < 0.3.4`. ## Patches Upgrade to `bsv-sdk >= 0.8.2` **and/or** `bsv-wallet >= 0.3.4`. Both releases ship the same fix: a new module `BSV::Wallet::CertificateSignature` (`lib/bsv/wallet_interface/certificate_signature.rb`), which builds the BRC-52 canonical preimage (`type`, `serial_number`, `subject`, `certifier`, `revocation_outpoint`, lexicographically-sorted `fields`) and verifies the certifier's signature against it via `ProtoWallet#verify_signature` with protocol ID `[2, 'certificate signature']` and counterparty = the claimed certifier's public key. Both `acquire_via_direct` and `acquire_via_issuance` now call `CertificateSignature.verify!` before returning the certificate to `acquire_certificate`, so invalid certificates raise `BSV::Wallet::CertificateSignature::InvalidError` (a subclass of `InvalidSignatureError`) and are never written to storage. Consumers should upgrade whichever gem they depend on directly; they do not need both. `bsv-wallet 0.3.4` additionally tightens its dependency on `bsv-sdk` from the stale `~> 0.4` to `>= 0.8.2, < 1.0`, which forces the known-good pairing and pulls in the sibling advisory fixes (F1.3, F5.13) tracked separately. The issuance-path fix also partially closes finding **F8.16** from the same compliance review. F8.16's second aspect — switching the issuance transport from ad-hoc JSON POST to BRC-104 AuthFetch — is not addressed here and remains deferred to a future release. Fixed in sgbett/bsv-ruby-sdk#306. ## Workarounds If upgrading is not immediately possible: - Do not expose `acquire_certificate` (either acquisition protocol) to untrusted callers. - Do not invoke `acquire_certificate` with `acquisition_protocol: 'issuance'` against a certifier URL you do not fully trust, and require TLS for any such request. - Treat any record returned by `list_certificates` / `prove_certificate` as unverified and perform an out-of-band BRC-52 verification against the certifier's public key before acting on it. ## Credit Identified during the 2026-04-08 cross-SDK compliance review, tracked as findings F8.15 (direct path) and F8.16 (issuance path, partial). ## References - HLR: sgbett/bsv-ruby-sdk#305 - Fix PR: sgbett/bsv-ruby-sdk#306 - Compliance review: [`.architecture/reviews/20260408-cross-sdk-compliance-review.md`](../../.architecture/reviews/20260408-cross-sdk-compliance-review.md) - BRC-52 specification: https://brc.dev/52 - TypeScript reference: `Certificate.verify()` in `@bsv/sdk`

CVE-2026-40070 Affected Bsv sdk Versions

2 component(s)
Fixed Versions:
0.8.20.3.4
Product / Package Ecosystem Affected Versions Fixed Version
bsv-sdk
RubyGems
≥ 0.3.1
< 0.8.2
0.8.2
bsv-wallet
RubyGems
≥ 0.1.2
< 0.3.4
0.3.4

References

Frequently Asked Questions

What is CVE-2026-40070?
CVE-2026-40070 is a security vulnerability in Bsv sdk involving bsv-sdk and bsv-wallet persist unverified certifier signatures in acquire_certificate (direct and issuance paths) under CWE-347: Improper Verification of Cryptographic Signature.
Which Bsv sdk versions are affected?
Affected versions include releases prior to 0.8.2, 0.3.4 across affected packages: bsv-sdk, bsv-wallet.
What version fixes CVE-2026-40070?
Upgrading to 0.8.2, 0.3.4 (or the latest patched release for your respective branch) resolves the vulnerability.
Is bsv-sdk affected?
Yes, bsv-sdk is affected in releases prior to 0.8.2. Upgrade your dependency to 0.8.2 or later.
Is bsv-wallet affected?
Yes, bsv-wallet is affected in releases prior to 0.3.4. Upgrade your dependency to 0.3.4 or later.
What is the CVSS score of CVE-2026-40070?
CVE-2026-40070 has a CVSS v3.1 base score of 8.1 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N.
What CWE is associated with CVE-2026-40070?
CVE-2026-40070 is classified under CWE-347: Improper Verification of Cryptographic Signature (The product does not verify, or incorrectly verifies, the cryptographic signature for data.).
How can I check RubyGems dependencies for CVE-2026-40070?
Run the dependency tree command: 'inspect dependencies for bsv-sdk'. 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-hc36-c89j-5f4j",
  "modified" : "2026-05-13T16:21:47Z",
  "published" : "2026-04-09T20:28:10Z",
  "aliases" : [ "CVE-2026-40070" ],
  "summary" : "bsv-sdk and bsv-wallet persist unverified certifier signatures in acquire_certificate (direct and issuance paths)",
  "details" : "# Unverified certifier signatures persisted by `acquire_certificate`\n\n## Affected packages\n\nBoth `bsv-sdk` and `bsv-wallet` are published from the [sgbett/bsv-ruby-sdk](https://github.com/sgbett/bsv-ruby-sdk) repository. The vulnerable code lives in `lib/bsv/wallet_interface/wallet_client.rb`, which is **physically shipped inside both gems** (the `bsv-wallet.gemspec` `files` list bundles the entire `lib/bsv/wallet_interface/` tree). Consumers of either gem are independently vulnerable; the two packages are versioned separately, so each has its own affected range.\n\n| Package | Affected | Patched |\n| --- | --- | --- |\n| `bsv-sdk` | `>= 0.3.1, < 0.8.2` | `0.8.2` |\n| `bsv-wallet` | `>= 0.1.2, < 0.3.4` | `0.3.4` |\n\n## Summary\n\n`BSV::Wallet::WalletClient#acquire_certificate` persists certificate records to storage **without verifying the certifier's signature** over the certificate contents. Both acquisition paths are affected:\n\n- `acquisition_protocol: 'direct'` — the caller supplies all certificate fields (including `signature:`) and the record is written to storage verbatim.\n- `acquisition_protocol: 'issuance'` — the client POSTs to a certifier URL and writes whatever signature the response body contains, also without verification.\n\nAn attacker who can reach either API (or who controls a certifier endpoint targeted by the issuance path) can forge identity certificates that subsequently appear authentic to `list_certificates` and `prove_certificate`.\n\n## Details\n\nBRC-52 requires a certificate's `signature` field to be verified against the claimed certifier's public key over a canonical hashing of `(type, subject, serialNumber, revocationOutpoint, fields)` before the certificate is trusted. The reference TypeScript SDK enforces this in `Certificate.verify()`.\n\n### Direct path\n\nThe Ruby implementation's `acquire_via_direct` path (`lib/bsv/wallet_interface/wallet_client.rb`) constructs the certificate record directly from caller-supplied fields:\n\n```ruby\ndef acquire_via_direct(args)\n  {\n    type: args[:type],\n    subject: @key_deriver.identity_key,\n    serial_number: args[:serial_number],\n    certifier: args[:certifier],\n    revocation_outpoint: args[:revocation_outpoint],\n    signature: args[:signature],\n    fields: args[:fields],\n    keyring: args[:keyring_for_subject]\n  }\nend\n```\n\nThe returned record is then written to the storage adapter by `acquire_certificate`. No verification of `args[:signature]` against `args[:certifier]`'s public key occurs at any point in this path.\n\n### Issuance path\n\n`acquire_via_issuance` POSTs to a certifier-supplied URL and parses the response body into a certificate record, which is then written to storage without verifying the returned signature. A hostile or compromised certifier endpoint — or anyone able to redirect/MITM the plain HTTP request — can therefore return an arbitrary `signature` value for any subject and have it stored as authentic. This is the same class of bypass as the direct path; it was tracked separately as finding **F8.16** in the compliance review and is closed by the same fix.\n\n### Downstream impact\n\nDownstream reads via `list_certificates` and selective-disclosure via `prove_certificate` treat stored records as valid without re-verifying, so any forgery that slips past `acquire_certificate` is trusted permanently.\n\n## Impact\n\nAny caller that can invoke `acquire_certificate` — via either acquisition protocol — can forge a certificate attributed to an arbitrary certifier identity key, containing arbitrary fields, and have it persisted as authentic. Applications and downstream gems that rely on the wallet's certificate store as a source of truth for identity attributes (e.g. KYC assertions, role claims, attestations) are subject to credential forgery.\n\nThis is a credential-forgery primitive, not merely a spec divergence from BRC-52.\n\n## CVSS rationale\n\n`AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N` → **8.1 (High)**\n\n- **AV:N** — network-reachable in any wallet context that exposes `acquire_certificate` to callers.\n- **AC:L** — low attack complexity: pass arbitrary bytes as `signature:`.\n- **PR:L** — low privileges: any caller authorised to invoke `acquire_certificate`.\n- **UI:N** — no user interaction required.\n- **C:H** — forged credentials via `prove_certificate` can assert attributes about the subject.\n- **I:H** — the wallet's credential store is polluted with attacker-controlled data.\n- **A:N** — availability unaffected.\n\n## Proof of concept\n\n```ruby\nclient = BSV::Wallet::WalletClient.new(key, storage: BSV::Wallet::MemoryStore.new)\n\nclient.acquire_certificate(\n  type: 'age-over-18',\n  acquisition_protocol: 'direct',\n  certifier: claimed_trusted_pubkey_hex,\n  serial_number: 'any-serial',\n  revocation_outpoint: ('00' * 32) + '.0',\n  signature: 'deadbeef' * 16,       # arbitrary bytes — never verified\n  fields: { 'verified' => 'true' },\n  keyring_for_subject: {}\n)\n\nclient.list_certificates(\n  certifiers: [claimed_trusted_pubkey_hex],\n  types: ['age-over-18']\n)\n# => returns the forged record as if it were a real certificate from that certifier\n```\n\n## Affected versions\n\nThe vulnerable direct-path code was introduced in commit `d14dd19` (\"feat(wallet): implement BRC-100 identity certificate methods (Phase 5)\") on 2026-03-27 20:35 UTC. The vulnerable issuance-path code was added one day later in `6a4d898` (\"feat(wallet): implement certificate issuance protocol\", 2026-03-28 04:38 UTC), which removed an earlier `raise UnsupportedActionError` and replaced it with an unverified HTTP POST.\n\n**`bsv-sdk`:** the v0.3.1 chore bump (`89de3a2`) was committed 28 minutes after `d14dd19`, so the direct-path bypass shipped in the **v0.3.1** tag. The v0.3.1 release raised `UnsupportedActionError` for the issuance path, so the issuance-path bypass first shipped in **v0.3.2** (`5a335de`). Every subsequent release up to and including **v0.8.1** is affected by at least one path, and every release from v0.3.2 onwards is affected by both. Combined affected range: `>= 0.3.1, < 0.8.2`.\n\n**`bsv-wallet`:** at the time both commits landed, the wallet gem was at version 0.1.1. The first wallet release containing any of the vulnerable code was **v0.1.2** (`5a335de`, 2026-03-30), which shipped both paths simultaneously. Every subsequent release up to and including **v0.3.3** is affected on both paths. Affected range: `>= 0.1.2, < 0.3.4`.\n\n## Patches\n\nUpgrade to `bsv-sdk >= 0.8.2` **and/or** `bsv-wallet >= 0.3.4`. Both releases ship the same fix: a new module `BSV::Wallet::CertificateSignature` (`lib/bsv/wallet_interface/certificate_signature.rb`), which builds the BRC-52 canonical preimage (`type`, `serial_number`, `subject`, `certifier`, `revocation_outpoint`, lexicographically-sorted `fields`) and verifies the certifier's signature against it via `ProtoWallet#verify_signature` with protocol ID `[2, 'certificate signature']` and counterparty = the claimed certifier's public key. Both `acquire_via_direct` and `acquire_via_issuance` now call `CertificateSignature.verify!` before returning the certificate to `acquire_certificate`, so invalid certificates raise `BSV::Wallet::CertificateSignature::InvalidError` (a subclass of `InvalidSignatureError`) and are never written to storage.\n\nConsumers should upgrade whichever gem they depend on directly; they do not need both. `bsv-wallet 0.3.4` additionally tightens its dependency on `bsv-sdk` from the stale `~> 0.4` to `>= 0.8.2, < 1.0`, which forces the known-good pairing and pulls in the sibling advisory fixes (F1.3, F5.13) tracked separately.\n\nThe issuance-path fix also partially closes finding **F8.16** from the same compliance review. F8.16's second aspect — switching the issuance transport from ad-hoc JSON POST to BRC-104 AuthFetch — is not addressed here and remains deferred to a future release.\n\nFixed in sgbett/bsv-ruby-sdk#306.\n\n## Workarounds\n\nIf upgrading is not immediately possible:\n\n- Do not expose `acquire_certificate` (either acquisition protocol) to untrusted callers.\n- Do not invoke `acquire_certificate` with `acquisition_protocol: 'issuance'` against a certifier URL you do not fully trust, and require TLS for any such request.\n- Treat any record returned by `list_certificates` / `prove_certificate` as unverified and perform an out-of-band BRC-52 verification against the certifier's public key before acting on it.\n\n## Credit\n\nIdentified during the 2026-04-08 cross-SDK compliance review, tracked as findings F8.15 (direct path) and F8.16 (issuance path, partial).\n\n## References\n\n- HLR: sgbett/bsv-ruby-sdk#305\n- Fix PR: sgbett/bsv-ruby-sdk#306\n- Compliance review: [`.architecture/reviews/20260408-cross-sdk-compliance-review.md`](../../.architecture/reviews/20260408-cross-sdk-compliance-review.md)\n- BRC-52 specification: https://brc.dev/52\n- TypeScript reference: `Certificate.verify()` in `@bsv/sdk`",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "RubyGems",
      "name" : "bsv-sdk"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0.3.1"
      }, {
        "fixed" : "0.8.2"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "RubyGems",
      "name" : "bsv-wallet"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0.1.2"
      }, {
        "fixed" : "0.3.4"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/sgbett/bsv-ruby-sdk/security/advisories/GHSA-hc36-c89j-5f4j"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-40070"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/sgbett/bsv-ruby-sdk/issues/305"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/sgbett/bsv-ruby-sdk/pull/306"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/sgbett/bsv-ruby-sdk/commit/4992e8a265fd914a7eeb0405c69d1ff0122a84cc"
  }, {
    "type" : "WEB",
    "url" : "https://brc.dev/52"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/bsv-sdk/CVE-2026-40070.yml"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/bsv-wallet/CVE-2026-40070.yml"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/sgbett/bsv-ruby-sdk"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-347" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-04-09T20:28:10Z",
    "nvd_published_at" : "2026-04-09T18:17:03Z"
  }
}