BTC
ETH
SOL
BNB
GOLD
XRP
DOGE
ADA
Back to home
Security

[HIGH] Security Advisory: bsv-sdk and bsv-wallet persist unverified certifier signatures in acquire_certificate (direct and issuance paths) (bsv-sdk, bsv-wallet)

Two Ruby gems for Bitcoin SV—bsv-sdk and bsv-wallet—store identity certificates without verifying the certifier's signature.

Two Ruby gems for Bitcoin SV—bsv-sdk and bsv-wallet—store identity certificates without verifying the certifier’s signature. This flaw affects bsv-sdk versions 0.3.1 through 0.8.1 and bsv-wallet versions 0.1.2 through 0.3.3. Developers patched it in bsv-sdk 0.8.2 and bsv-wallet 0.3.4. Update immediately if you use these ranges.

The vulnerability sits in the acquire_certificate method of BSV::Wallet::WalletClient, a class bundled into both gems from the same GitHub repo: sgbett/bsv-ruby-sdk. Attackers can forge certificates that the wallet later treats as legitimate when calling list_certificates or prove_certificate. In BSV’s ecosystem, these certificates follow BRC-52, a standard for on-chain identity proofs tying subjects to public keys via signed metadata like serial numbers and revocation outpoints.

Vulnerable Acquisition Paths

The bug hits both ways to get certificates: direct and issuance.

In the direct path, acquire_via_direct takes user-supplied fields—including the signature—and stores them verbatim. No check happens against the certifier’s public key. Here’s the code:

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

Supply a fake signature over fake fields, and it lands in storage as truth. BRC-52 demands hashing (type, subject, serialNumber, revocationOutpoint, fields) and verifying it against the certifier’s key—something the TypeScript reference SDK does in Certificate.verify(), but Ruby skips.

The issuance path posts to a certifier’s URL over plain HTTP, parses the response, and stores the signature unchecked. A compromised certifier, MITM attacker, or redirect poisons the wallet with junk certs. This echoes classic API security fails: trust no input, verify everything.

Why This Matters in BSV

BSV pushes massive blocks for enterprise use, with tools like these SDKs enabling wallet apps and identity layers. Certificates prove control over identities for payments, access, or smart contracts. Forged certs let attackers impersonate users, drain funds, or hijack services relying on prove_certificate.

Consider the blast radius: Both gems share the flawed lib/bsv/wallet_interface/ tree, despite separate versioning. If your Rails app, script, or service imports either, you’re exposed independently. No CVEs yet, but this qualifies as high severity—authentication bypass in a crypto wallet library.

BSV’s BRC-52 aims to standardize certs amid fragmented identity solutions post-Bitcoin forks. Skipping verification undermines that. Reference implementations matter; Ruby’s deviation invites exploits. Fair point: maintainers fixed it fast after audit findings (F8.16 for issuance). But bundling wallet client into the SDK blurs lines—why not separate concerns?

Check your Gemfile.lock. Run bundle outdated | grep bsv to spot vulnerable versions. After updating:

$ gem update bsv-sdk bsv-wallet
$ bundle update bsv-sdk bsv-wallet

Audit your code: Scan for acquire_certificate calls. Manually verify certs post-acquisition using BRC-52 logic. Test list_certificates output against known good certs. In production, proxy issuance requests over HTTPS only, and pin certifiers.

This exposes Ruby’s crypto ecosystem gaps. BSV devs, lean on audited libs like the TypeScript SDK for compliance. For others, it reinforces: In finance and security tools, unverified signatures equal unlocked doors. Patch now, verify always.

April 10, 2026 · 3 min · 13 views · Source: GitHub Security

Related