fix(core/cardano): don't access TR in global ctx
What changed, and why it matters
This commit is a code-quality fix in the Cardano app of the Trezor firmware. It removes direct access to the global translation object (TR) at the time the Python module is first loaded, and instead reads the translated strings only when they are actually needed. This avoids a potential startup-time crash or import-order problem if the translation system is not fully initialized when the module is imported. There is no direct evidence in the commit that this is an exploitable security vulnerability.
Treat as a routine defensive fix. Review whether any other modules access TR at import time and could fail similarly. No urgent security response is indicated by this commit alone.
Security signals we found
Global-context access to translation object removed
Class-level constants converted to runtime properties
No input validation, cryptography, or authorization changes
No explicit security impact described by vendor
Evidence from the diff
The patch changes several Cardano signer classes from class-level constants (SIGNING_MODE_TITLE = TR.cardano__…) to instance properties (def signing_mode_title(self) -> str: return TR.cardano__…). It also replaces a module-level constant CVOTE_REWARD_ELIGIBILITY_WARNING with direct TR access inside functions. The effect is to defer access to the global translation table TR until runtime, preventing module-import-time evaluation of TR. The commit message states this is a fix for ‘don’t access TR in global ctx’. No changelog entry is requested.
Changed components
core/src/apps/cardano/layout.pycore/src/apps/cardano/sign_tx/multisig_signer.pycore/src/apps/cardano/sign_tx/ordinary_signer.pycore/src/apps/cardano/sign_tx/plutus_signer.pycore/src/apps/cardano/sign_tx/pool_owner_signer.pycore/src/apps/cardano/sign_tx/signer.pyInspect captured patch +22 / −11
diff --git a/core/src/apps/cardano/layout.py b/core/src/apps/cardano/layout.py
index 64f666f1..15fa7759 100644
--- a/core/src/apps/cardano/layout.py
+++ b/core/src/apps/cardano/layout.py
@@ -75,7 +75,6 @@ CERTIFICATE_TYPE_NAMES = {
BRT_Other = ButtonRequestType.Other # global_import_cache
-CVOTE_REWARD_ELIGIBILITY_WARNING = TR.cardano__reward_eligibility_warning
_DEFAULT_MAX_DISPLAYED_CHUNK_SIZE = 56
@@ -447,7 +446,9 @@ async def show_cvote_registration_payment_credentials(
payment_credential, intro_text, purpose="cvote_reg_payment_address"
)
if show_both_credentials or show_payment_warning:
- extra_text = CVOTE_REWARD_ELIGIBILITY_WARNING if show_payment_warning else None
+ extra_text = (
+ TR.cardano__reward_eligibility_warning if show_payment_warning else None
+ )
await _show_credential(
stake_credential,
intro_text,
@@ -1008,7 +1009,7 @@ async def confirm_cvote_registration_payment_address(
(TR.cardano__rewards_go_to, payment_address, True),
]
if should_show_payment_warning:
- props.append((None, CVOTE_REWARD_ELIGIBILITY_WARNING, None))
+ props.append((None, TR.cardano__reward_eligibility_warning, None))
await confirm_properties(
"confirm_cvote_registration_payment_address",
title=TR.cardano__confirm_transaction,
diff --git a/core/src/apps/cardano/sign_tx/multisig_signer.py b/core/src/apps/cardano/sign_tx/multisig_signer.py
index 11e2b030..aa1fc583 100644
--- a/core/src/apps/cardano/sign_tx/multisig_signer.py
+++ b/core/src/apps/cardano/sign_tx/multisig_signer.py
@@ -14,7 +14,9 @@ class MultisigSigner(Signer):
The multisig signing mode only allows signing with multisig (and minting) keys.
"""
- SIGNING_MODE_TITLE = TR.cardano__confirming_a_multisig_transaction
+ @property
+ def signing_mode_title(self) -> str:
+ return TR.cardano__confirming_a_multisig_transaction
def _validate_tx_init(self) -> None:
msg = self.msg # local_cache_attribute
diff --git a/core/src/apps/cardano/sign_tx/ordinary_signer.py b/core/src/apps/cardano/sign_tx/ordinary_signer.py
index 0871c1ff..cde9b521 100644
--- a/core/src/apps/cardano/sign_tx/ordinary_signer.py
+++ b/core/src/apps/cardano/sign_tx/ordinary_signer.py
@@ -19,7 +19,9 @@ class OrdinarySigner(Signer):
controlled by 1852' keys, dealing with staking and minting/burning tokens.
"""
- SIGNING_MODE_TITLE = TR.cardano__confirming_transaction
+ @property
+ def signing_mode_title(self) -> str:
+ return TR.cardano__confirming_transaction
def __init__(
self,
@@ -78,7 +80,7 @@ class OrdinarySigner(Signer):
# for OrdinarySigner, we do not show the prompt to choose level of details
if self.suite_tx_type is SuiteTxType.NOT_SUITE_TX:
self.should_show_details = await layout.show_tx_init(
- self.SIGNING_MODE_TITLE
+ self.signing_mode_title
)
else:
self.should_show_details = False
diff --git a/core/src/apps/cardano/sign_tx/plutus_signer.py b/core/src/apps/cardano/sign_tx/plutus_signer.py
index 33d870d7..144a17f9 100644
--- a/core/src/apps/cardano/sign_tx/plutus_signer.py
+++ b/core/src/apps/cardano/sign_tx/plutus_signer.py
@@ -16,7 +16,9 @@ class PlutusSigner(Signer):
validation rules are less strict, but more tx items/warnings are shown to the user.
"""
- SIGNING_MODE_TITLE = TR.cardano__confirming_a_plutus_transaction
+ @property
+ def signing_mode_title(self) -> str:
+ return TR.cardano__confirming_a_plutus_transaction
async def _show_tx_init(self) -> None:
await super()._show_tx_init()
diff --git a/core/src/apps/cardano/sign_tx/pool_owner_signer.py b/core/src/apps/cardano/sign_tx/pool_owner_signer.py
index 532b8755..1e4a0ce5 100644
--- a/core/src/apps/cardano/sign_tx/pool_owner_signer.py
+++ b/core/src/apps/cardano/sign_tx/pool_owner_signer.py
@@ -22,7 +22,9 @@ class PoolOwnerSigner(Signer):
staking key in the list of pool owners.
"""
- SIGNING_MODE_TITLE = TR.cardano__confirming_pool_registration
+ @property
+ def signing_mode_title(self) -> str:
+ return TR.cardano__confirming_pool_registration
def _validate_tx_init(self) -> None:
msg = self.msg # local_cache_attribute
diff --git a/core/src/apps/cardano/sign_tx/signer.py b/core/src/apps/cardano/sign_tx/signer.py
index 985cc2f4..61917793 100644
--- a/core/src/apps/cardano/sign_tx/signer.py
+++ b/core/src/apps/cardano/sign_tx/signer.py
@@ -28,7 +28,7 @@ from ..helpers.utils import derive_public_key
if TYPE_CHECKING:
from buffer_types import AnyBytes
from enum import IntEnum
- from typing import Any, Awaitable, ClassVar
+ from typing import Any, Awaitable
from trezor.enums import CardanoAddressType
@@ -99,7 +99,9 @@ class Signer:
user confirmation and serialization of the tx item.
"""
- SIGNING_MODE_TITLE: ClassVar[str]
+ @property
+ def signing_mode_title(self) -> str:
+ raise NotImplementedError
def __init__(
self,
@@ -266,7 +268,7 @@ class Signer:
validate_network_info(msg.network_id, msg.protocol_magic)
async def _show_tx_init(self) -> None:
- self.should_show_details = await layout.show_tx_init(self.SIGNING_MODE_TITLE)
+ self.should_show_details = await layout.show_tx_init(self.signing_mode_title)
if not self._is_network_id_verifiable():
await layout.warn_tx_network_unverifiable()
Why this scored 20/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.