chore(ethereum): replace load-bearing asserts
What changed, and why it matters
This commit replaces several 'assert' checks in the Ethereum 'clear signing' code with proper error handling. In production firmware, asserts can be stripped out or behave differently than expected, so replacing them with explicit error raises makes the code more robust against malformed or malicious transaction data. The change is defensive hardening rather than a clear fix for an active exploit.
Treat as a security-hardening improvement. Review whether remaining assert isinstance checks should also be converted to explicit exceptions, and verify that InvalidFormatDefinition is handled safely upstream without crashing the device or leaking sensitive state. No immediate incident response is indicated absent further evidence.
Security signals we found
Replacement of load-bearing assert statements with explicit exceptions
Input validation for parsed Ethereum transaction calldata
Defensive hardening in transaction signing display logic
Potential assert-stripping risk in production firmware builds
Evidence from the diff
The patch modifies core/src/apps/ethereum/clear_signing.py, changing load-bearing assertions in _handle_approve() and _handle_transfer() to explicit InvalidFormatDefinition exceptions. It validates that parsed calldata yields exactly two arguments and two fields, and that field names match expected values (‘Spender’/’Amount’ for approve, ‘To’/’Amount’ for transfer). Type assertions remain as asserts. This reduces reliance on assert for control flow and input validation, which is a security best practice because asserts may be disabled in optimized builds or behave unexpectedly in embedded/Micropython environments.
Changed components
core/src/apps/ethereum/clear_signing.pyEthereum clear signing transaction parsing_handle_approve()_handle_transfer()Inspect captured patch +18 / −10
diff --git a/core/src/apps/ethereum/clear_signing.py b/core/src/apps/ethereum/clear_signing.py
index bf15a317..c03942a4 100644
--- a/core/src/apps/ethereum/clear_signing.py
+++ b/core/src/apps/ethereum/clear_signing.py
@@ -912,18 +912,22 @@ async def _handle_approve(
args, fields = await display_format.parse_calldata(calldata, msg, defs)
- assert len(args) == 2
- assert len(fields) == 2
+ if len(args) != 2 or len(fields) != 2:
+ raise InvalidFormatDefinition
arg0_raw_value = args[0]
(field0_name, recipient_addr, _), _, _ = fields[0]
- assert field0_name == "Spender"
+ if field0_name != "Spender":
+ raise InvalidFormatDefinition
+
assert isinstance(arg0_raw_value, bytes)
assert isinstance(recipient_addr, str)
arg1_raw_value = args[1]
(field1_name, value, _), actual_token, _ = fields[1]
- assert field1_name == "Amount"
+ if field1_name != "Amount":
+ raise InvalidFormatDefinition
+
assert isinstance(arg1_raw_value, int)
recipient_str = KNOWN_ADDRESSES.get(arg0_raw_value)
@@ -964,17 +968,21 @@ async def _handle_transfer(
args, fields = await display_format.parse_calldata(calldata, msg, defs)
- assert len(args) == 2
- assert len(fields) == 2
+ if len(args) != 2 or len(fields) != 2:
+ raise InvalidFormatDefinition
+
+ (field0_name, recipient_addr, _), _, _ = fields[0]
+ if field0_name != "To":
+ raise InvalidFormatDefinition
- (arg0_name, recipient_addr, _), _, _ = fields[0]
- assert arg0_name == "To"
assert isinstance(recipient_addr, str)
arg1_raw_value = args[1]
+ (field1_name, value, _), actual_token, _ = fields[1]
+ if field1_name != "Amount":
+ raise InvalidFormatDefinition
+
assert isinstance(arg1_raw_value, int)
- (arg1_name, value, _), actual_token, _ = fields[1]
- assert arg1_name == "Amount"
assert isinstance(value, str)
if payment_request_verifier:
Why this scored 46/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.