v0.1.1
Status Update: 29 September 2026
Developer preview. Do not use with real signing keys or treat the review as a safety guarantee.
The assets attached here are still v0.1.1. Later parser, acknowledgement and browser-interface fixes on main are not included in these downloads. See the current changelog and verification status before testing.
The follow-up review behind this release was AI-assisted, not a second independent human audit. This version also accepts the legacy leading-# acknowledgement syntax; the original notes incorrectly described that syntax as reliably rejected.
Only the canonical aarch64 Linux binary has the documented reproducibility comparison. Compilation uses a local registry cache; the container bootstrap still downloads dependencies. Desktop installers are unsigned. No assets or tags were replaced by this note update.
Original release notes (superseded claims corrected above)
Update from v0.1.0 if you review batched transactions. A second independent
review found a decoding gap that could hide a dangerous call from you.
Fixed
A dangerous call past the display limit was never named. A Safe MultiSend
batch shows 32 calls and parses up to 1024. The calls past the display limit
were checked for DELEGATECALL and for an invalid operation byte, and then
reported only as "some calls are not shown". A call at position 33 granting an
unlimited token approval, or changing the Safe's owners, threshold or
implementation, got no finding of its own.
v0.1.0 reports such a batch as BLIND, so it still ends in DO NOT SIGN — it was
never silent. But the specific reason was missing, and INV-6 says those
actions are CRITICAL. Every call is now judged by the same rules whether or not
there is room to display it, with the findings grouped by code so a long batch
stays readable.
Two findings sharing a code in one plan step needed only one
acknowledgement. In the authority engine, requirements were keyed on
(step, code), so duplicates merged. Reachable through SignTransaction: a
batch granting unlimited approvals to two different spenders produced two
UNLIMITED_APPROVAL findings, and confirming once approved both — to two
different addresses. Findings are now numbered as the review displays them,
which is what the transaction signer has always done.
This affects authority and the authority command-line tool. The transaction
reviewer was never affected.
The window contacted Google every time it opened. It fetched a webfont from
fonts.googleapis.com on load. For a tool whose value is that it talks to
nothing, that told a third party who was reviewing a transaction, and when. The
request is gone and the font allowances are out of the application's content
security policy.
Corrected claims
"Never touches a network" was too broad. Fetching a queued transaction by
its hash contacts Safe's transaction service, by design. The decoder still never
opens a socket, and the signer image has no network stack compiled into its
kernel — those are the precise statements, and they are stronger than the loose
one.
"Offline" overstated the canonical build. The compile is offline from a
copied registry cache. The container's own bootstrap is not: it installs three
packages with apt and downloads rustup, neither pinned by digest. The
recorded hashes say so now. Pinning the bootstrap is the obvious next step and
has not been done.
Interface change
authority --ack now takes the number beside the finding rather than the step
number: --ack 2:SECRET_EGRESS, not --ack #5:SECRET_EGRESS. A leading # is
still accepted so an acknowledgement copied from an older transcript is refused
loudly rather than misread. Scripts that acknowledged by step number need
updating.
Also
A fuzz target was building its acknowledgements by deduplicating on
(step, code) — the same assumption the engine was making — so it agreed with
the bug and could never have found it. About 6.5 million executions proved
nothing on that path. It now asks the review what it requires.
A tool for reading a Safe transaction before you approve it. It holds no
keys and signs nothing.
The decoder never opens a socket. Paste a transaction and nothing
leaves the machine. The one feature that does reach the network is
fetching a queued transaction by its hash, which contacts Safe's
transaction service and nothing else.
Start with README.md in the archive, or
docs/06-using-it-before-you-sign.md in the repository.
clearsign safe-json tx.json --chain-id 1
What is checked, and what is not. This has had one external security
review: ten findings, all fixed. The fixes have not been reviewed by
anyone outside the project. docs/03-verification-status.md lists what
is proven and what is not, including the gaps.
Reproducibility. The aarch64-unknown-linux-musl build is the one
you can check, and it is built here the same way you would rebuild it:
in the canonical container, offline, with build paths remapped out.
Rebuild it with signing-core/scripts/reproducible-cross-check.sh and
compare against signing-core/EXPECTED-HASHES.txt.
Compare the binary, not the archive. BINARY-SHA256 attached here
is the binary's hash; SHA256SUMS covers the archives, which include a
README and the licences and so hash differently.
The macOS and x86_64 builds are produced by GitHub's runners and are
not reproducible in that sense — rustc does not promise identical
output across compiler hosts, and this project would rather say so than
imply otherwise.
The application is not signed yet. macOS and Windows will warn that
it comes from an unidentified developer, because it does: signing
certificates are a paid registration this project has not taken out.
Until then the honest check is the hash, not the badge.
Not for real keys. The signing and seed commands stay behind a
development guard. Anything typed into an everyday computer should be
treated as exposed.