fix(core): use `IntEnum = int` in run-time
What changed, and why it matters
This commit fixes a type-stub mismatch in Trezor firmware. During normal runtime, the code was using a placeholder `IntEnum = object`, which made enum-like values behave as plain objects rather than integers. The fix changes the runtime alias to `IntEnum = int`, so integer-like behavior works as expected. The change is small and affects multiple files that define integer-backed enums. Without deeper context, it is unclear whether this caused an exploitable security bug, but it could have led to subtle logic errors in cryptographic/transaction code.
Treat as a correctness fix with potential security side effects. Review whether any `IntEnum` usage in the affected files relied on integer comparison, bitwise operations, or enum member lookup that could have misbehaved under `object`. Consider adding regression tests and a changelog/security note if a concrete vulnerability is identified. No immediate emergency action is warranted based solely on this diff.
Security signals we found
Runtime type stub mismatch could cause incorrect enum/integer behavior in security-critical code paths
Affected components include transaction signing (Bitcoin, Cardano, Solana, Zcash) and bech32 address encoding
No explicit security framing, CVE, or changelog entry from the vendor
Cherry-pick from another commit suggests backport of a bugfix
Evidence from the diff
The patch replaces runtime-only IntEnum = object stubs with IntEnum = int across six files. In MicroPython runtime builds (TYPE_CHECKING is false), the previous stub meant classes inheriting from IntEnum were actually inheriting from object, so IntEnum(arg) would return a new non-integer instance and integer operations/comparisons could behave incorrectly. The fix restores expected integer semantics. The affected files include Bitcoin, Cardano, Solana, Zcash, bech32 encoding, and the THP wire protocol. The commit message frames this as a runtime correctness fix, not a security fix, and includes ‘[no changelog]’.
Changed components
core/src/apps/bitcoin/common.pycore/src/apps/cardano/sign_tx/signer.pycore/src/apps/solana/types.pycore/src/apps/zcash/unified_addresses.pycore/src/trezor/crypto/bech32.pycore/src/trezor/wire/thp/__init__.pyInspect captured patch +6 / −6
### core/src/apps/bitcoin/common.py
@@ -18,7 +18,7 @@
from apps.common.coininfo import CoinInfo
else:
- IntEnum = object
+ IntEnum = int
BITCOIN_NAMES = ("Bitcoin", "Regtest", "Testnet", "Signet")
### core/src/apps/cardano/sign_tx/signer.py
@@ -41,7 +41,7 @@
CardanoTxResponseType = CardanoTxItemAck | messages.CardanoTxWitnessResponse
else:
- IntEnum = object
+ IntEnum = int
_MINTING_POLICY_ID_LENGTH = const(28)
### core/src/apps/solana/types.py
@@ -25,7 +25,7 @@
T = TypeVar("T")
else:
- IntEnum = object
+ IntEnum = int
T = 0
Generic = {T: object}
### core/src/apps/zcash/unified_addresses.py
@@ -13,7 +13,7 @@
from apps.common.coininfo import CoinInfo
else:
- IntEnum = object
+ IntEnum = int
# Saves 50 bytes over `def prefix(coin: CoinInfo) -> str`
### core/src/trezor/crypto/bech32.py
@@ -39,7 +39,7 @@
# but not (None, somelist)
OptionalTuple2 = tuple[None, None] | tuple[A, B]
else:
- IntEnum = object
+ IntEnum = int
class Encoding(IntEnum):
### core/src/trezor/wire/thp/__init__.py
@@ -13,7 +13,7 @@
from trezor.wire import WireInterface
else:
- IntEnum = object
+ IntEnum = int
class ThpUnallocatedSessionError(WireError):Why this scored 34/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.