Skip to content

Fix cerberus#1025

Closed
cedelavergne-ledger wants to merge 5 commits into
developfrom
cev/fix_cerberus
Closed

Fix cerberus#1025
cedelavergne-ledger wants to merge 5 commits into
developfrom
cev/fix_cerberus

Conversation

@cedelavergne-ledger
Copy link
Copy Markdown
Contributor

Description

Please provide a detailed description of what was done in this PR.
(And mentioned if linked to an issue docs)

Changes include

  • Bugfix (non-breaking change that solves an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (change that is not backwards-compatible and/or changes current functionality)
  • Tests
  • Documentation
  • Other (for changes that might not fit in any category)

The home-screen plugin tagline builder accumulated the FORMAT_PLUGIN
template length and the caller-controlled caller_app->name length into
a uint8_t. A sufficiently long caller name could wrap that accumulator,
leading to an undersized allocation for g_tag_line and a subsequent
snprintf overflow into adjacent memory across the on-device library-call
trust boundary.

Bound the plugin name with strnlen() against an explicit maximum and
perform the length math in size_t to make the wrap unreachable.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@cedelavergne-ledger cedelavergne-ledger requested a review from a team as a code owner May 11, 2026 13:10
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.04%. Comparing base (0f2cae5) to head (da96a88).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #1025   +/-   ##
========================================
  Coverage    56.04%   56.04%           
========================================
  Files           26       26           
  Lines         2414     2414           
  Branches       323      323           
========================================
  Hits          1353     1353           
  Misses        1057     1057           
  Partials         4        4           
Flag Coverage Δ
unittests 56.04% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 11, 2026

elf sizes
source = source branch cev/fix_cerberus
target = target branch develop

Device .text source .text target .text delta .bss source .bss target .bss delta max stack size source max stack size target max stack size delta
flex 181069 180557 512 21810 21794 16 15048 15064 -16
nanox 115027 114003 1024 20536 20520 16 8192 8192 0
apex_p 160921 159897 1024 21810 21794 16 19144 19160 -16
nanos2 115299 114275 1024 20508 20492 16 20448 20464 -16
stax 180990 179966 1024 21810 21794 16 15048 15064 -16

Stack consumption summary

⚠️ This summary is for informative purpose only. It may not give the application actual worst case, for example if the test coverage is low.

Device Worst case (bytes) Remaining stack (bytes) Test
apex_p 3193 15951 test_eip712.py::test_eip712_batch[apex_p]
nanox 3193 4999 test_eip712.py::test_eip712_batch[nanox]
stax 3193 11855 test_eip712.py::test_eip712_batch[stax]

Full details

cedelavergne-ledger and others added 4 commits May 11, 2026 16:06
…th swap

The EIP-7702 authorization handler kept no signing state. handle_sign_
eip7702_authorization() accepted a new P1_FIRST_CHUNK at any time and
immediately overwrote tmpCtx.authSigningContext7702.bip32 before the
TLV payload was complete. Because tlv_from_apdu() returns success for
buffered partial payloads, a hostile host could start a second
authorization mid-review, swap the BIP32 path, and have auth_7702_ok_cb
sign the displayed authorization hash with a different derivation path
than the one shown on screen.

Introduce a dedicated APP_STATE_SIGNING_EIP7702 and gate the handler
on it: refuse P1_FIRST_CHUNK unless idle, refuse continuation chunks
without an active session, and clear the state on error or on
approval (auth_7702_cancel_cb already resets via send_status).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both staking plugins set uiType=ETH_UI_TYPE_GENERIC, which suppresses
the standard Amount/To pair. The review then displayed only the
withdrawal-request amount or validator pubkeys parsed from calldata,
never the native tx.value carried by the transaction. A malicious dApp
could attach an arbitrary ETH/native amount to a staking-style request
and have the user authorize it without seeing the value on screen.

Add a "Tx value" review screen to both EIP-7002 and EIP-7251 plugins
whenever the transaction's native value is non-zero, and adjust the
screen index → screen kind mapping so the existing validator/amount
screens remain in their expected order.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The ERC1155 safeBatchTransferFrom (0x2eb2c2d6) review path explicitly
skipped copying token IDs (`// don't copy anything since we won't
display it`) and summed every value into a single context->value. The
device then only rendered "<total> from <count> NFT IDs", which let a
malicious dApp slip a high-value token ID into a batch of innocuous
ones without the user being able to detect it on-screen.

Capture the first ERC1155_BATCH_DISPLAY_MAX (id, value) pairs into the
plugin context, render each pair on its own pair of screens, and add
an explicit "WARNING — Only first N of M IDs shown" screen whenever
the batch is larger than what we can surface. The aggregate Total
Quantity screen is preserved.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
handle_set_plugin() parsed the signed chain_id only to call
app_compatible_with_chain_id() and then discarded it. The stored
tokenContext kept the plugin name, contract address, and selector but
never the chain the registration was signed for. eth_plugin_perform_
init_default() therefore authorized the plugin solely on address +
selector match, which let a host preload a valid signed registration
for chain A and then route a transaction on chain B through the same
plugin UI, masking attacker-controlled calldata behind a familiar
review flow.

Store the signed chain_id alongside the registration and refuse to
activate the plugin when the transaction's chain_id differs.
set_external_plugin keeps its chain-unbound semantics (its signed
payload contains no chain_id) and is marked explicitly via
PLUGIN_CHAIN_ID_ANY; cross-chain protection there requires a protocol
change and is left out of scope.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants