fix(solana): fall back to generic UI for more ALT references
What changed, and why it matters
This update fixes a display bug in Trezor's Solana token-transfer confirmation screen. When a token transfer uses Solana Address Lookup Tables (ALTs) to refer to the token mint or the owner account, the device previously showed the lookup-table address as if it were the real account address. That could trick a user into approving a transfer they did not fully understand. The fix makes these cases fall back to a more cautious, generic confirmation screen that clearly marks ALT references.
Treat as a security-hardening fix with user-impact. Users should update firmware when available. Developers reviewing Solana transaction flows should verify that any account field that can be an ALT reference is handled by the generic ALT-aware UI rather than the predefined flow.
Security signals we found
UI spoofing / misleading display of account addresses
Address Lookup Table (ALT) reference not resolved on-device
User confirmation bypass risk due to incorrect address rendering
Security changelog entry present
Evidence from the diff
In core/src/apps/solana/predefined_transaction.py, is_predefined_token_transfer() now checks whether token_mint, destination_account, or owner is an ALT reference (is_address_reference). Previously only destination_account was checked. If any of these three fields is an ALT reference, the function returns False so the predefined token-transfer UI is skipped and the generic ALT-aware UI is used instead. Tests were expanded to cover ALT-referenced mint and owner cases.
Changed components
Trezor Core Solana appcore/src/apps/solana/predefined_transaction.pySolana SPL token transfer predefined transaction flowInspect captured patch +57 / −7
### core/.changelog.d/+solana_alt_refs.security
@@ -0,0 +1 @@
+Solana: Fixed token transfer showing the lookup-table address for ALT-referenced mint and owner accounts.
### core/src/apps/solana/predefined_transaction.py
@@ -103,10 +103,19 @@ def is_predefined_token_transfer(
owner = transfer_token_instructions[0].owner[0]
for transfer_token_instruction in transfer_token_instructions:
- if is_address_reference(transfer_token_instruction.destination_account):
- # ALT-referenced destination can't be resolved on-device, fall back
+ if any(
+ map(
+ is_address_reference,
+ (
+ transfer_token_instruction.token_mint,
+ transfer_token_instruction.destination_account,
+ transfer_token_instruction.owner,
+ ),
+ )
+ ):
+ # ALT-referenced accounts can't be resolved on-device, fall back
# to the generic reference-aware display instead of showing the
- # lookup table address as the recipient.
+ # lookup table address as the actual account.
return False
if (
transfer_token_instruction.program_id != token_program
### core/tests/test_apps.solana.predefined_transaction.py
@@ -129,17 +129,19 @@ def create_transfer_token_instruction(
token_mint="GHArwcWCuk9WkUG4XKUbt935rKfmBmywbEWyFxdH3mou",
destination_account="92YgwqTtTWB7qY92JT6mbL2WCmhAs7LPZL4jLcizNfwx",
owner="14CCvQzQzHCVgZM3j9soPnXuJXh1RmCfwLVUcdfbZVBS",
+ mint_is_reference=False,
destination_is_reference=False,
+ owner_is_reference=False,
):
return create_mock_instruction(
program_id,
instruction_id,
{
- "token_mint": create_account(token_mint),
+ "token_mint": create_account(token_mint, mint_is_reference),
"destination_account": create_account(
destination_account, destination_is_reference
),
- "owner": create_account(owner),
+ "owner": create_account(owner, owner_is_reference),
},
)
@@ -290,6 +292,24 @@ def test_is_predefined_token_transfer(self):
create_transfer_token_instruction(),
create_transfer_token_instruction(destination_is_reference=True),
],
+ # ALT-referenced token mint, can't be resolved on-device
+ [
+ create_transfer_token_instruction(mint_is_reference=True),
+ ],
+ # one direct and one ALT-referenced token mint
+ [
+ create_transfer_token_instruction(),
+ create_transfer_token_instruction(mint_is_reference=True),
+ ],
+ # ALT-referenced owner, can't be resolved on-device
+ [
+ create_transfer_token_instruction(owner_is_reference=True),
+ ],
+ # one direct and one ALT-referenced owner
+ [
+ create_transfer_token_instruction(),
+ create_transfer_token_instruction(owner_is_reference=True),
+ ],
]
for instructions in valid_test_cases:
### core/tests/test_apps.solana.predefined_transaction.py.mako
@@ -58,17 +58,19 @@ def create_transfer_token_instruction(
token_mint="GHArwcWCuk9WkUG4XKUbt935rKfmBmywbEWyFxdH3mou",
destination_account="92YgwqTtTWB7qY92JT6mbL2WCmhAs7LPZL4jLcizNfwx",
owner="14CCvQzQzHCVgZM3j9soPnXuJXh1RmCfwLVUcdfbZVBS",
+ mint_is_reference=False,
destination_is_reference=False,
+ owner_is_reference=False,
):
return create_mock_instruction(
program_id,
instruction_id,
{
- "token_mint": create_account(token_mint),
+ "token_mint": create_account(token_mint, mint_is_reference),
"destination_account": create_account(
destination_account, destination_is_reference
),
- "owner": create_account(owner),
+ "owner": create_account(owner, owner_is_reference),
},
)
@@ -219,6 +221,24 @@ class TestSolanaPredefinedTransactions(unittest.TestCase):
create_transfer_token_instruction(),
create_transfer_token_instruction(destination_is_reference=True),
],
+ # ALT-referenced token mint, can't be resolved on-device
+ [
+ create_transfer_token_instruction(mint_is_reference=True),
+ ],
+ # one direct and one ALT-referenced token mint
+ [
+ create_transfer_token_instruction(),
+ create_transfer_token_instruction(mint_is_reference=True),
+ ],
+ # ALT-referenced owner, can't be resolved on-device
+ [
+ create_transfer_token_instruction(owner_is_reference=True),
+ ],
+ # one direct and one ALT-referenced owner
+ [
+ create_transfer_token_instruction(),
+ create_transfer_token_instruction(owner_is_reference=True),
+ ],
]
for instructions in valid_test_cases:Why this scored 61/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.