diff --git a/gems/bsv-sdk/CVE-2026-40069.yml b/gems/bsv-sdk/CVE-2026-40069.yml new file mode 100644 index 0000000000..789743799f --- /dev/null +++ b/gems/bsv-sdk/CVE-2026-40069.yml @@ -0,0 +1,147 @@ +--- +gem: bsv-sdk +cve: 2026-40069 +ghsa: 9hfr-gw99-8rhx +url: https://github.com/sgbett/bsv-ruby-sdk/security/advisories/GHSA-9hfr-gw99-8rhx +title: bsv-sdk ARC broadcaster treats INVALID/MALFORMED/ORPHAN + responses as successful broadcasts +date: 2026-04-09 +description: | + # ARC broadcaster treats failure statuses as successful broadcasts + + ## Summary + + `BSV::Network::ARC`'s failure detection only recognises `REJECTED` + and `DOUBLE_SPEND_ATTEMPTED`. ARC responses with `txStatus` values + of `INVALID`, `MALFORMED`, `MINED_IN_STALE_BLOCK`, or any + `ORPHAN`-containing `extraInfo` / `txStatus` are silently treated + as successful broadcasts. Applications that gate actions on broadcaster + success are tricked into trusting transactions that were never + accepted by the network. + + ## Details + + `lib/bsv/network/arc.rb` (lines ~74-100 in the affected code) uses a + narrow failure predicate compared to the TypeScript reference SDK. + The TS broadcaster additionally recognises: + + - `INVALID` + - `MALFORMED` + - `MINED_IN_STALE_BLOCK` + - Any response containing `ORPHAN` in `extraInfo` or `txStatus` + + The Ruby implementation omits all of these, so ARC responses + carrying any of these statuses are returned to the caller as + successful broadcasts. + + Additional divergences in the same module compound the risk: + + - `Content-Type` is sent as `application/octet-stream`; the TS + reference sends `application/json` with a `{ rawTx: }` + body (EF form where source transactions are available). + - The headers `XDeployment-ID`, `X-CallbackUrl`, and `X-CallbackToken` + are not sent. + + The immediate security-relevant defect is the missing failure + statuses; the other divergences are fixed in the same patch for + protocol compliance. + + ## Impact + + Integrity: callers receive a success response for broadcasts that + were actually rejected by the ARC endpoint. Applications and + downstream gems that gate actions on broadcaster success — releasing + goods, marking invoices paid, treating a token as minted, progressing + a workflow — are tricked into trusting transactions that were never broadcast. + + This is an integrity bug with security consequences. It does not + disclose information (confidentiality unaffected) and does not + affect availability. + + ## CVSS rationale + + `AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N` → **7.5 (High)** + + - **AV:N** — network-reachable. + - **AC:L** — no specialised access conditions are required. Triggering + any of the unhandled failure statuses is not meaningfully harder + than broadcasting a transaction at all: a malformed or invalid + transaction, an orphan condition from a transient fork, or a + hostile/misbehaving ARC endpoint returning one of these statuses + is sufficient. The attacker does not need to defeat any mitigation + or race a specific window — the bug is that the code path doesn't + exist at all. + - **PR:N** — no privileges required. + - **UI:N** — no user interaction. + - **C:N** — no confidentiality impact. + - **I:H** — downstream integrity decisions are taken on + non-broadcast transactions. + - **A:N** — no availability impact. + + ## Affected versions + + The ARC broadcaster was introduced in commit `a1f2e62` ("feat(network): + add ARC broadcaster with injectable HTTP client") on 2026-02-08 and + first released in **v0.1.0**. The narrow failure predicate has been + present since introduction. Every release up to and including **v0.8.1** + is affected. + + Affected range: `>= 0.1.0, < 0.8.2`. + + ## Patches + + Upgrade to `bsv-sdk >= 0.8.2`. The fix: + + - Expands the failure predicate (`REJECTED_STATUSES` + `ORPHAN` + substring check on both `txStatus` and `extraInfo`) to include + `INVALID`, `MALFORMED`, `MINED_IN_STALE_BLOCK`, and any + orphan-containing response, matching the TypeScript reference. + - Switches `Content-Type` to `application/json` with a `{ rawTx: }` + body, preferring Extended Format (BRC-30) hex when every input has + `source_satoshis` and `source_locking_script` populated and falling + back to plain raw-tx hex otherwise. + - Adds support for the `XDeployment-ID` (default: random + `bsv-ruby-sdk-`), `X-CallbackUrl`, and `X-CallbackToken` + headers via new constructor keyword arguments. + + Fixed in sgbett/bsv-ruby-sdk#306. + + ### Note for `bsv-wallet` consumers + + The sibling gem `bsv-wallet` (published from the same repository) is + not independently vulnerable — `lib/bsv/network/arc.rb` is not bundled + into the wallet gem's `files` list. However, `bsv-wallet` runtime-depends + on `bsv-sdk`, so a consumer of `bsv-wallet` that also invokes the + ARC broadcaster is transitively exposed whenever `Gemfile.lock` + resolves to a vulnerable `bsv-sdk` version. `bsv-wallet >= 0.3.4` + tightens its `bsv-sdk` constraint to `>= 0.8.2, < 1.0`, so upgrading + either gem is sufficient to pull in the fix. + + ## Workarounds + + If upgrading is not immediately possible: + + - Verify broadcast results out-of-band (e.g. query a block explorer + or WhatsOnChain) before treating a transaction as broadcast. + - Do not gate integrity-critical actions solely on the ARC + broadcaster's success response. + + ## Credit + + Identified during the 2026-04-08 cross-SDK compliance review, + tracked as finding F5.13. +cvss_v3: 7.5 +unaffected_versions: + - "< 0.1.0" +patched_versions: + - ">= 0.8.2" +related: + url: + - https://nvd.nist.gov/vuln/detail/CVE-2026-40069 + - https://github.com/sgbett/bsv-ruby-sdk/releases/tag/v0.8.2 + - https://github.com/sgbett/bsv-ruby-sdk/pull/306 + - https://github.com/sgbett/bsv-ruby-sdk/commit/4992e8a265fd914a7eeb0405c69d1ff0122a84cc + - https://github.com/sgbett/bsv-ruby-sdk/issues/305 + - https://github.com/sgbett/bsv-ruby-sdk/security/advisories/GHSA-9hfr-gw99-8rhx + - https://advisories.gitlab.com/pkg/gem/bsv-sdk/CVE-2026-40069 + - https://github.com/advisories/GHSA-9hfr-gw99-8rhx diff --git a/gems/bsv-sdk/CVE-2026-40070.yml b/gems/bsv-sdk/CVE-2026-40070.yml new file mode 100644 index 0000000000..eee3800744 --- /dev/null +++ b/gems/bsv-sdk/CVE-2026-40070.yml @@ -0,0 +1,236 @@ +--- +gem: bsv-sdk +cve: 2026-40070 +ghsa: hc36-c89j-5f4j +url: https://github.com/sgbett/bsv-ruby-sdk/security/advisories/GHSA-hc36-c89j-5f4j +title: bsv-sdk and bsv-wallet persist unverified certifier signatures + in acquire_certificate (direct and issuance paths) +date: 2026-04-09 +description: | + # 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). + +cvss_v3: 8.1 +unaffected_versions: + - "< 0.3.1" +patched_versions: + - ">= 0.8.2" +related: + url: + - https://nvd.nist.gov/vuln/detail/CVE-2026-40070 + - https://github.com/sgbett/bsv-ruby-sdk/security/advisories/GHSA-hc36-c89j-5f4j + - https://github.com/sgbett/bsv-ruby-sdk/pull/306 + - https://github.com/sgbett/bsv-ruby-sdk/commit/4992e8a265fd914a7eeb0405c69d1ff0122a84cc + - https://github.com/sgbett/bsv-ruby-sdk/issues/305 + - https://bsv.brc.dev/peer-to-peer/0052 + - https://advisories.gitlab.com/pkg/gem/bsv-sdk/CVE-2026-40070/ + - https://github.com/advisories/GHSA-hc36-c89j-5f4j diff --git a/gems/bsv-wallet/CVE-2026-40070.yml b/gems/bsv-wallet/CVE-2026-40070.yml new file mode 100644 index 0000000000..e494a46f6b --- /dev/null +++ b/gems/bsv-wallet/CVE-2026-40070.yml @@ -0,0 +1,238 @@ +--- +gem: bsv-wallet +cve: 2026-40070 +ghsa: hc36-c89j-5f4j +url: https://github.com/sgbett/bsv-ruby-sdk/security/advisories/GHSA-hc36-c89j-5f4j +title: bsv-sdk and bsv-wallet persist unverified certifier signatures + in acquire_certificate (direct and issuance paths) +date: 2026-04-09 +description: | + # 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 + 8 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). +cvss_v3: 8.1 +unaffected_versions: + - "< 0.1.2" +patched_versions: + - ">= 0.3.4" +related: + url: + - https://nvd.nist.gov/vuln/detail/CVE-2026-40070 + - https://github.com/sgbett/bsv-ruby-sdk/security/advisories/GHSA-hc36-c89j-5f4j + - https://github.com/sgbett/bsv-ruby-sdk/pull/306 + - https://github.com/sgbett/bsv-ruby-sdk/commit/4992e8a265fd914a7eeb0405c69d1ff0122a84cc + - https://github.com/sgbett/bsv-ruby-sdk/issues/305 + - https://bsv.brc.dev/peer-to-peer/0052 + - https://advisories.gitlab.com/pkg/gem/bsv-wallet/CVE-2026-40070 + - https://github.com/advisories/GHSA-hc36-c89j-5f4j