Date: March-April 2023
Auditors: Amaury (https://github.com/amaurym), Facundo (https://github.com/facundomedica)
SIGN_MODE_TEXTUAL is a new string-based sign mode that is targetted at signing with hardware devices. It is specified in ADR-050.
In 2022-2023, the Cosmos SDK team led a working group with Agoric, Confio, StrangeLove and Zondax to implement SIGN_MODE_TEXTUAL. As part of its Quality Assurance process, this working group is conducting an internal audit to identify potential security issues, inefficiencies and non-compliance to the specification.
This document describes the results of the internal audit.
Seven findings were identified and categorized into Specification, Implementation, Testing, and Documentation. Their severities ranged from Informational to Medium, no critical issues were found. The most critical issue was the lack of a boolean value renderer which would prevent any message including a bool value from being signed using sign mode textual. The findings where addressed in PRs or tracked in a GitHub issue.
The internal audit is performed on the https://github.com/cosmos/cosmos-sdk repository, at commit hash a8dceddad91cf0b00b20c4f7d4260583719a6403
(March 20th, 2023).
The scope limited to the following files and folders:
docs/architecture/adr-050-sign-mode-textual.md
docs/architecture/adr-050-sign-mode-textual-annex1.md
docs/architecture/adr-050-sign-mode-textual-annex2.md
x/tx/signing/textual/*
)
x/tx/signing/textual/tx.go
x/tx/signing/textual/handler.go
x/tx/signing/textual/internal/cbor
x/tx/signing/textual/encode.go
x/auth/tx/textual.go
x/auth/tx/config.NewTextualWithBankKeeper
x/auth/tx/config.NewTextualWithGRPCConn
The methodology is based on the "Module Readiness Checklist" by the Cosmos SDK, which has been used as an internal audit template when introducing new SDK modules (e.g. authz, feegrant, groups). The template can be found in the Cosmos SDK repository.
It has been slightly adapted, as SIGN_MODE_TEXTUAL is not an SDK module.
The following checklist should be run for each item in the Scope.
ID | Title | Category | Severity | Status |
---|---|---|---|---|
01-ANY-SPEC | Any value renderer spec update |
Documentation | Low | Solved |
02-COIN-TEST | Coin value renderer "zero" test case |
Testing | Low | Solved |
03-MSG-TEST | Message value renderer spec update |
Documentation | Informational | Solved |
04-ANY-HEADER | Any value renderer header mismatch |
Implementation | Low | Solved |
05-MSG-DUPCODE | Message value renderer duplicated code |
Implementation | Low | Solved |
06-BOOL-RDR | Bool value renderer missing | Specification | Medium | Solved |
07-OFFLINE-SIGN | Offline signing is not possible | Implementation | Medium | TO-DO, not planned |
Finding Category
Finding Severity:
Any
value renderer spec updateID: 01-ANY-SPEC
Category: Documentation
Severity: Low
Status: Solved in https://github.com/cosmos/cosmos-sdk/pull/15550
Artifacts: Annex 1.
Description: As discussed during a Working Group call, it was decided to remove the header screen for messages. The implementation was done https://github.com/cosmos/cosmos-sdk/pull/15208, however the specification was not updated accordingly.
Recommendation: Update the specification to match the agreed upon decision and the implementation. Also add in-code comments to reference this spec.
Coin
value renderer "zero" test caseID: 02-COIN-TEST
Category: Testing
Severity: Low
Status: Solved in https://github.com/cosmos/cosmos-sdk/pull/15550
Artifacts: x/tx/signing/textual/coins.go
Description: The specification describes empty coin encoded as "zero"
. The x/tx/signing/textual/internal/testdata/coin.json
however did not contain a test case for this.
Recommendation: Add the test case for "zero"
.
Message
value renderer spec updateID: 03-MSG-SPEC
Category: Documentation
Severity: Low
Status: Solved in https://github.com/cosmos/cosmos-sdk/pull/15550
Artifacts: Annex 1.
Description: The specification describes a special case for sdk.Msg
message, which was then abandoned in a Working Group call.
Recommendation: Remove the special case for sdk.Msg
, clarify specification more.
Any
value renderer header mismatchID: 04-ANY-HEADER
Category: Implementation
Severity: Low
Status: Solved in https://github.com/cosmos/cosmos-sdk/pull/15550
Artifacts: x/tx/signing/textual/any.go
Description: The Any
value-renderer contains the code:
_, isMsgRenderer := vr.(*messageValueRenderer)
if isMsgRenderer && subscreens[0].Content == fmt.Sprintf("%s object", internalMsg.ProtoReflect().Descriptor().Name()) {
If the first condition isMsgRenderer
is true, then the second condition also must be true, or else it's an implementation error upstream (in the protobuf values passed into Textual), and the user should be aware of it.
Recommendation: Throw an error if the second condition doesn't pass.
_, isMsgRenderer := vr.(*messageValueRenderer)
- if isMsgRenderer && subscreens[0].Content == fmt.Sprintf("%s object", internalMsg.ProtoReflect().Descriptor().Name()) {
+ if isMsgRenderer {
+ if subscreens[0].Content != fmt.Sprintf("%s object", internalMsg.ProtoReflect().Descriptor().Name()) {
+ return nil, fmt.Errorf("any internal message expects %s, got %s", fmt.Sprintf("%s object", internalMsg.ProtoReflect().Descriptor().Name()), subscreens[0].Content)
+ }
}
Message
value renderer duplicated codeID: 05-MSG-DUPCODE
Category: Implementation
Severity: Low
Status: Solved in https://github.com/cosmos/cosmos-sdk/pull/15715
Artifacts: x/tx/signing/textual/message.go
Description: The Message
value renderer made use of a hardcoded suffix in many places instead of using an already existing method for this (instead of fmt.Sprintf("%s object", ...)
use header()
).
ID: 06-BOOL-RDR
Category: Implementation/Spec
Severity: Medium/High
Status: Solved in https://github.com/cosmos/cosmos-sdk/pull/15863
Description: There is no bool value renderer, meaning that any message that contains a bool can't be signed and will throw an error (for example x/gov proposal's expedited field is a boolean).
ID: 07-OFFLINE-SIGN
Category: Implementation
Severity: Low
Status: Tracked in https://github.com/cosmos/cosmos-sdk/issues/15864
Description: Sign mode textual requires a GRPC connection or a bank keeper to query a denom's metadata in order to display it correctly; none of which will/should be available if –offline is being passed.