Faraday's first audit
Welcome to the Faraday Blog! I am @bitcoinpasada, and I really hope you will find something of value from the Faraday project. And in case you're starved to read something written by a human, you've found the right place.
I never expected to be writing Faraday's first blog article to explain that an audit revealed several critical and high level vulnerabilities inside Faraday. In a way, however, it feels very fitting to be doing exactly that. What follows in this article is both a post-mortem on the first audit my little project has received and my thoughts about where that leaves us.
The audit was generously performed by Mr. Hodl (GitHub), to whom I am extremely grateful! I am purposefully keeping the blog version of the post mortem very brief. Rather than focus on all the technicals of the audit's findings (1, 2) and Faraday's fixes (both are very fascinating reads nonetheless), I realized that there is no better time to address the nature of my approach in this project than right here at the outset.
I have a feeling that I'm not the only person out there who is slightly unsettled by the fact there are so many AI coded projects popping up — and ones that want to touch your keys to boot! (By the way I was using the em-dash long before AI so I get to keep using it — I'm grandfathered in). At first glance, every project can't help but seem suspicious. And it feels almost preposterous that we would even consider swapping out trusted hardware vendors, professional programmers, expensive third party audits, and secure elements, for what are essentially vibe-coded passion projects. What a time to be alive! Before I go any further into the philosophy behind Faraday, let's go through the audit brief.
The audit results and fixes
Mr. Hodl's audit, which was performed by DeepSeek V4.1, Kimi K3, and GLM 5.3 (Wow thank you again for your efforts on this Mr. Hodl!) found two critical, and five high level security vulnerabilities. By my own audit definitions critical means a key, seed or passphrase can be extracted, the device signs or shows as approved something you did not approve, Faraday's output is wrong in a way that loses funds, or crafted input runs code on Faraday. High means the same but only under specific conditions (physical access, a non-default setting, a rare input), or that secrets outlive the session, a tampered image is accepted, or the design makes a costly mistake likely. And seven of these in total, ouch!
First, the two critical issues (full disclosure: Claude drafted the following issue explainer points and I edited):
- FROST threshold signing. When a FROST wallet signed across more than one place, the first device made up every co-signer's secret nonce and carried them over to the next place in a file — which meant that anyone holding that file (or the first device itself) could work out another signer's share from the signature they made. Ouch. The fix? FROST is gone from Faraday entirely until its standards are actually published. A little backstory here: my own review had caught this same flaw on October 23rd, and FROST came out of the app the very next day, so 0.1.7 never offered it (0.1.6 and earlier did). The audits read the code itself, though, which still had FROST in it — so they were right to flag it! In fact, that review was the one that led me to first write down the standards Faraday follows today, and this very flaw is what led to Faraday's rule that only published standards, checked against someone else's implementation, make it into the app. FROST has now been removed from the repository completely, and it will only come back once it meets those standards.
- Multisig change. If you hadn't registered your multisig wallet on the device, Faraday would accept as "your change" any output whose script merely contained one of your keys. A dishonest coordinator could have sent your change to a script they control, and Faraday would have shown you the transaction as perfectly fine. Now Faraday goes a step further: it won't sign a multisig spend at all unless that wallet is registered on the device, so your change is always checked against the real wallet — never the coordinator's word. And if the transaction carries the cosigners' keys (most coordinators include them), registering takes a single hold: Faraday shows you the threshold and every cosigner, checks that they really make up the wallet being spent from, and remembers it. This now matches how the major hardware signers handle it — Coldcard, for example, refuses a multisig transaction that doesn't match a wallet registered on the device.
And the five high issues:
- Taproot key path. A taproot multisig wallet whose key path belonged to somebody else looked exactly like a safe "2 of 3". Sneaky! Now Faraday tells you who can spend by the key path, and if it's a key that isn't one of the wallet's own, you get a big red warning that you have to hold to accept — and it stays on the wallet's card and comes back on every spend.
- Copying Faraday to another stick. The device's "Upgrade a Faraday stick" trusted its source stick just by a version string and a size, so someone with physical access could have slipped a tampered image onto your next stick. Rather than patch it, I pulled the feature out completely. Faraday no longer writes boot partitions at all — sticks get upgraded with Faraday Starter, which checks every image against the signed release.
- Silent payments. The scan key in a silent payments wallet record was never checked against your own key, so a tampered record could have shown you an address that quietly pays someone else. Now both keys are checked, the address comes from your key, and a record that doesn't match gets refused and shown for what it is.
- Already-finalized inputs. An input marked as "already finalized" skipped the check that stops a coordinator from understating SegWit amounts across two signing rounds — the old trick for sneaking in a giant hidden fee. Finalized inputs now go through exactly the same check as every other input.
- QR codes of secrets. When you showed a secret as a QR code, a few copies made while drawing it weren't wiped from memory when you closed the view. Small, but secrets shouldn't linger — now everything that touched the secret gets wiped as soon as it's no longer on screen.
One very important result of the audit is that it led to a new standard in Faraday. While thinking about the multisig change issue, I kept coming back to one question: “Is there any honest reason someone would need to sign for a multisig wallet they haven’t registered?” There isn’t, so Faraday now simply refuses. With that question in mind, I had Claude go through every warning in Faraday that a person can click past and ask the same question of each one. The answer became a new standard: Faraday never lets you past a check that keeps your keys or money safe unless there’s a real case that needs it. Where there is one, Faraday tells you what isn’t being checked and why, and you have to hold the approval button for a few seconds to go on. This review turned a few warnings into outright refusals (a transaction spending a timelocked path early, which the network would never accept, for one). A few stayed, now behind a hold, because they have honest uses, such as paying a big fee to move a stuck transaction, or using a TV as your screen. And change that Faraday can’t prove is yours is now shown as a payment.
In addition, the audit included 34 medium and 48 low issues. It was very interesting and encouraging for me to see that Claude actually elevated no medium but two low issues to high in its own review of the audit (plus one more from findings the auditors themselves had disputed). In the end only six low level items were left unaddressed in the code, each with a stated reason in the full report (1, 2).
My personal comment
If you've read this far, you must, like me, have an inkling that there might be more than meets the eye to the validity of such novel approaches to designing keystores and Bitcoin signers. As we have seen, the first audit of such a project may reveal several critical issues. But also, we have all been witness to some amazing security disclosures over the past several weeks, with critical vulnerabilities in battle-tested software being unveiled on a near-daily basis. Every piece of software in the world is going through the same hardening process right now, in real time.
From this perspective, Faraday is simply one among many, and its path to acceptance is the same as any other software. The important point is that small projects such as this one are taking advantage of the same defensive strategies available to everyone. I believe this means that in practice, Faraday can be hardened and "proven" much more quickly than software in the past. How many audits would you want to see stating that there are no critical or high vulnerabilities found before you would start to trust it? 3? 5? 10 audits from different models and humans too? Please excuse my deliberate use of the word "trust" in that last sentence — it is only meant to convey that ultimately, there is a root of trust in ANY hardware or software project. I'm doing everything I can to minimize trust in Faraday — our documentation already explains the measures currently in place to make human audits easy as well as ensure that our cryptography and overall security architecture is working as intended. Forthcoming blog posts will spell it all out in plain English. Eventually, there just becomes no point in not admitting that the thing does what it says it does, and it does so safely. In the end, time and community acceptance will be the test of its worth.
In this post I have only touched on the software aspect of Faraday — but the code is only one part of the attack surface. In my next blog post, I want to address the question I have been asked, and that you are right to ask: "Is it safe to enter a Bitcoin key on a normal, everyday laptop?" I firmly believe that for many people, the tradeoffs may be worth it. Regardless, the Pi image remains available for those who feel safer that way. I will discuss this further in future posts. Let me just say for now that even if you think you would never be comfortable booting into Faraday on your everyday driver, old or cheap new laptops abound! And your next "hardware wallet" will have a big screen and full keyboard...
Okay enough digression — this post is about the audit, which Claude is just wrapping up fixes for as I type. What started as a nerve-wracking first hour or two after receiving the report is ending with me breathing a sigh of relief and a having a feeling of increased confidence in my own work! Every critical and high finding is fixed in 0.1.8, along with every medium finding that held up and nearly all of the lows. The full report (1, 2) explains each decision, along with the few findings that turned out not to be problems. Version 0.1.8 (still pre-release) is up, and I do hope you'll give it a whirl! Much more to come, thank you for reading!
-bitcoinpasada