Prepared by:
HALBORN
Last Updated 08/05/2026
Date of Engagement: June 18th, 2026 - June 24th, 2026
100% of all REPORTED Findings have been addressed
All findings
16
Critical
0
High
0
Medium
5
Low
8
Informational
3
Cobault is a Bitcoin yield product that allows customers to earn a return on BTC holdings while retaining direct, self-sovereign custody of their funds. Each customer engagement is secured by its own individual Bitcoin vault implemented as a native 2-of-3 multisignature P2WSH contract. The contract descriptor is: wsh(or_d(multi(2, U, P, V), and_v(v:pk(U_refund), after(M))))
In plain terms, this creates two ways to spend from the vault:
Cooperatively, by any two of three independent parties signing together, or
Independently, by the customer alone, using a dedicated recovery key, after a pre-agreed block height M is reached on the Bitcoin blockchain.
The three signing parties are: the Customer (U), who holds their key in a browser-based key agent and never shares it; ProductCo (P), which holds a signing key in an isolated AWS account and runs the yield strategy on Deribit; and the Verifier (V), intended to be an independent foundation, which holds its own signing key, independently validates every withdrawal against the registered contract terms and settlement price, and maintains an immutable record of all agreements.
The Cobault Platform (TechCo) coordinates the system, but deliberately holds no vault signing key and cannot move funds unilaterally. [Architecture Deck, p.1–2]
The yield strategy is a bear-call-spread on BTC options, executed on Deribit. At settlement, the Verifier independently fetches the Deribit delivery price, recomputes the customer payout from the registered contract terms, and will only sign a withdrawal transaction whose outputs match that independent calculation to the satoshi. [Architecture Deck, p.5]
This assessment covers the Cobault system's security architecture and design. Three primary inputs were reviewed:
Architecture Deck v1: a detailed technical description of the vault design, component architecture, cryptographic primitives, account topology, and operational controls across all four trust domains (TechCo, ProductCo, Verifier, and Customer).
Nested Threat Surface and Mitigation Inventory: a design-facing threat inventory produced from a multi-repository source review of the Cobault codebase, covering twelve threat surface areas from vault signing authority through to CI/CD and supply chain. Critically, this document is explicit that it represents design intent and observed source code — not confirmed live deployment state.
Client responses: answers to specific verification questions raised during this assessment, covering block height sources, browser signing behaviour, spend path validation, IMDS configuration, CloudTrail logging, browser cryptographic libraries, production configuration, and Esplora operator identity.
The following is a record of controls and architectural decisions observed in the review that represent sound security practice. These are recorded here because a threat model should be an accurate picture of a system's security posture, not only a list of its weaknesses.
Non-custodial, per-transaction vault model. Each customer transaction is protected by its own independent vault. There is no pooling of funds, no shared signing authority across customers, and no rehypothecation. The design eliminates the class of failures — such as fractional reserve or mass-counterparty exposure — common in custodial models. [Architecture Deck, p.1]
Orchestrator holds no vault signing key. TechCo coordinates the entire system but is not a vault signer. The watcher, which builds and broadcasts transactions, holds the ProductCo key only through the productco-signer mediating service — it cannot call KMS directly. Admin controls can pause, cap, or halt operations but cannot grant new signing authority. This is a sound separation of coordination from custody. [Architecture Deck, p.6; Inventory, §5.1–5.2]
Customer timelock recovery is service-independent. After block height M, the customer can recover vault funds using only their own U_refund key, without any cooperation from Cobault, ProductCo, or the Verifier. This is enforced at the Bitcoin protocol level and holds even against a hostile Verifier (test case T34) or extended platform outage. [Architecture Deck, p.4; Inventory, §1.6]
SIGHASH_ALL enforcement. Both the ProductCo signer and the Verifier require SIGHASH_ALL on vault inputs, ensuring that any signature covers the full transaction — no output can be substituted after signing. [Inventory, §1.3; Client response Q3, verifier/services/verifier/src/lib.rs:1537]
Verifier independent settlement validation. Before signing any withdrawal, the Verifier independently fetches the Deribit settlement price, recomputes the customer/platform split from the immutable registered contract, and rejects any PSBT whose outputs deviate from that calculation. It also independently checks the chain tip and wall-clock time. No component of this validation is supplied by the orchestrator — it is derived entirely from the Verifier's own data sources. [Architecture Deck, p.5; Client response Q1, verifier/services/verifier/src/lib.rs:1112–1233]
All signing phases require Verifier countersignature. Confirmed by code review: phase_requires_verifier_sig returns true for all four defined signing phases with no fallback false case. The ProductCo signer verifies the Verifier's ECDSA signature against its own independently recomputed BIP-143 digest before using KMS. There is no currently orchestrated spend path that bypasses the Verifier. [Client response Q3, productco-signer/services/productco-signer/src/intent_validation.rs:473–516]
Content-addressed, append-only contract store. Vault contracts are stored content-addressed by canonical hash and are immutable after activation. Settlement records, refund signatures, price pins, and KMS key references are append-only, enforced by database triggers. These records are signed by the Verifier's Ed25519 identity key and can be independently verified. [Architecture Deck, p.13; Inventory, §4.2; verifier/services/verifier/migrations/0001_schema.sql:31,56,122,142,161]
Deterministic signing with audited libraries. Browser PSBT signing uses @scure/btc-signer v1.8.1, built on @noble/curves v1.9.7, which implements RFC 6979 HMAC-DRBG deterministic nonce generation.⁶ Seed generation uses @scure/bip39with crypto.getRandomValues, which throws if no secure random source is available. The signing path is covered by test vectors asserting deterministic output. [Client response Q6, user-app/web/key-agent/package-lock.json:473–490]
Canonical JSON with golden tests. All consequential messages use a deterministic serialisation defined in cobault-shared/canonical-json, with golden tests to ensure the same bytes are produced across all implementations and versions. This ensures that what is hashed is what is signed. [Architecture Deck, p.8]
Ed25519 service-to-service authentication with replay protection. All inter-service requests are authenticated using Ed25519 signatures over (timestamp, nonce, method, path/query, SHA-256 body hash). Nonces are consumed only after signature verification, and the in-memory nonce cache prevents replay. [Architecture Deck, p.2; cobault-shared/crates/cobault-auth/src/lib.rs:296,419]
Verifier identity rooted in a Nitro Enclave. The Verifier's Ed25519 identity key lives in an AWS Nitro Enclave. Decryption of the identity state is conditioned on the enclave's PCR0 attestation measurement via kms:RecipientAttestation:ImageSha384 — the key cannot be decrypted outside a verified enclave image. [Architecture Deck, p.7; cobault-verifier-keys-infra/infra/enclave.yaml:611,662,666]
Key isolation with sign-only KMS roles. ProductCo and Verifier vault keys are held in dedicated AWS accounts (ProductCo-KI and VerifierKeys-KI) separate from their operating workloads. KMS roles are restricted to kms:Sign and kms:GetPublicKey, with explicit IAM denies on decrypt, re-encrypt, export, key deletion, disable, policy mutation, and out-of-boundary signing. ABAC tag policies prevent consumer roles from modifying the cobault:keystore tag that gates key access. [Architecture Deck, p.7; cobault-productco-infra/infra/iam.yaml:116,204,216,233]
EKS Fargate for signer workloads. The ProductCo signer and Verifier API pods run on EKS Fargate, which has no EC2 instance metadata endpoint. This eliminates the IMDS credential-theft attack class for the primary signer workloads. [Client response Q4, cobault-productco-infra/infra/fargate-profile.yaml:38–52; cobault-verifier-infra/infra/fargate-profile.yaml:42–55]
IMDSv2 enforced on the enclave parent host. The only EC2 host in the signing path — the Verifier Nitro Enclave parent instance — is configured with HttpTokens: required and HttpPutResponseHopLimit: 2. The hop limit of 2 is correct for this deployment (the enclave supervisor runs in a container, which requires one additional hop). [Client response Q4, cobault-verifier-infra/infra/enclave.yaml:561–564]
kms:Sign captured by CloudTrail management events. AWS KMS cryptographic API calls, including kms:Sign, are captured by CloudTrail as management events when IncludeManagementEvents: true is set. Organisation-wide and key-org trails are configured with this setting and no ExcludeManagementEventSources: kms.amazonaws.com exclusion. [Client response Q5, cobault-shared/log-archive/org-cloudtrail.yaml:52–68]
Object Lock compliance-mode audit buckets for key organisations. Audit trails for the ProductCo-KI and VerifierKeys-KI accounts are stored in S3 buckets configured with Object Lock in Compliance mode — these records cannot be deleted or overwritten by any user, including account administrators, for the retention period. [Architecture Deck, p.7; cobault-productco-infra/infra/logging.yaml:99–116; cobault-verifier-keys-infra/infra/logging.yaml:99–116]
ProductCo signer pause state is persisted. The ProductCo signer maintains a pause state in Postgres (signer_admin_controlstable) that survives pod restarts. The /sign handler checks this flag before any vault or KMS work and returns 503 SIGNER_PAUSED if set. This provides a surgical, durable operational halt for the ProductCo signing path. [Client response Q5, productco-signer/services/productco-signer/migrations/0001_schema.sql:124–141]
Idempotent signing with immutable intent records. The ProductCo signer records signed intents with a primary key of (vault_id, phase, input_index), protected by an immutable database trigger that prevents modification or deletion. Duplicate requests return the cached signature; conflicting requests are rejected. This prevents double-signing and protects audit integrity. [Inventory, §3.3; productco-signer/services/productco-signer/migrations/0001_schema.sql:27,47,86]
Release-gating lifecycle tests. All custody-impacting changes must pass three end-to-end lifecycle tests on a private signet before deployment: T32 (full happy-path lifecycle), T33 (customer recovery via timelock after Verifier unavailability), and T34 (customer recovery after a hostile Verifier). These are not optional — they are release gates. [Architecture Deck, p.10]
Critical
0
High
0
Medium
5
Low
8
Informational
3
Impact x Likelihood
HAL-01
HAL-02
HAL-03
HAL-04
HAL-07
HAL-06
HAL-05
HAL-14
HAL-15
HAL-16
HAL-10
HAL-11
HAL-12
HAL-13
HAL-08
HAL-09
| Security analysis | Risk level | Remediation Date |
|---|---|---|
| Verifier operational independence | Medium | Risk Accepted - 07/02/2026 |
| Payout contract integrity at vault creation | Medium | Solved - 07/08/2026 |
| Transaction validation-to-signature integrity | Medium | Solved - 07/09/2026 |
| Customer transaction signing without independent output verification | Medium | Solved - 07/09/2026 |
| Operator console access controls and hardening | Medium | Risk Accepted - 07/20/2026 |
| Verifier signing halt mechanism | Low | Risk Accepted - 07/20/2026 |
| Customer seed loss and recovery path | Low | Solved - 07/16/2026 |
| Single source for settlement price data | Low | Risk Accepted - 07/02/2026 |
| Availability of single-replica signing services | Low | Solved - 07/20/2026 |
| Settlement price timing and ProductCo's position in the pricing process | Low | Solved - 07/08/2026 |
| Verifier identity key rotation and enclave image governance | Low | Risk Accepted - 07/20/2026 |
| Automated ITM settlement: chain-data source independence | Low | Solved - 07/20/2026 |
| Chain-data reliability and blockchain reorganisation handling | Low | Solved - 07/20/2026 |
| Vault provisioning integrity | Informational | Solved - 07/09/2026 |
| Verifier signing monitoring and audit trail completeness | Informational | Risk Accepted - 07/20/2026 |
| Instance metadata service exposure on signer infrastructure | Informational | Solved - 07/20/2026 |
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.
// Download the full report
Cobault - Blockchain Architecture Assessment
* Use Google Chrome for best results
** Check "Background Graphics" in the print settings if needed