From 1db2c4265bf61bf39f3142643ef15c586f807a00 Mon Sep 17 00:00:00 2001 From: Local Dev Date: Sun, 4 Oct 2026 02:10:51 +0200 Subject: [PATCH 1/2] Aegis: refuse a Tron transaction whose fields appear twice The decoder read the first copy of a singular protobuf field; java-tron keeps the last. Any.value is opaque bytes, so a TransferContract carrying two recipients and two amounts hashes to the same txid either way: the overlay showed "1 TRX to X" while the chain would move 999 TRX to another address. It also defeated the plan-time and sign-time draft checks against a hostile node. A repeated singular field, or a known field with the wrong wire type, now refuses the transaction. --- bundled-addons/aegis/lib/tron-decode.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/bundled-addons/aegis/lib/tron-decode.js b/bundled-addons/aegis/lib/tron-decode.js index 8ecc60ae..396fc3b9 100644 --- a/bundled-addons/aegis/lib/tron-decode.js +++ b/bundled-addons/aegis/lib/tron-decode.js @@ -81,9 +81,20 @@ module.exports = function makeTronDecode({ sha256, base58check }) { } return out; } - const one = (fields, n) => fields.find((f) => f.field === n); - const bytesOf = (fields, n) => { const f = one(fields, n); return f && f.wire === 2 ? f.value : null; }; - const numOf = (fields, n) => { const f = one(fields, n); return f && f.wire === 0 ? f.value : null; }; + // A singular field that appears twice is legal protobuf: the parser keeps + // the LAST copy (and merges repeated sub-messages). java-tron does that, so + // reading the first copy would show the user one recipient and amount while + // the chain executes another — and Any.value is opaque bytes, so the signed + // hash is the same either way. Refuse instead of guessing, and refuse a + // known field sent with the wrong wire type for the same reason. + const one = (fields, n, wire) => { + const hits = fields.filter((f) => f.field === n); + if (hits.length > 1) throw new Error(`field ${n} appears ${hits.length} times; refusing an ambiguous transaction`); + if (hits[0] && hits[0].wire !== wire) throw new Error(`field ${n} has wire type ${hits[0].wire}, expected ${wire}`); + return hits[0]; + }; + const bytesOf = (fields, n) => { const f = one(fields, n, 2); return f ? f.value : null; }; + const numOf = (fields, n) => { const f = one(fields, n, 0); return f ? f.value : null; }; // 21-byte Tron address (0x41 || h20) → "T…" base58check. Anything else is // returned as hex so the overlay never hides a malformed field. From bd113f9b477e6b5db0490f1f13ee56fc450b136f Mon Sep 17 00:00:00 2001 From: Local Dev Date: Sun, 4 Oct 2026 02:11:42 +0200 Subject: [PATCH 2/2] Aegis 0.30.1: the Tron duplicate-field fix, ahead of 0.31.0 0.30.0 is on the update channel and bundled in Theseus 0.3.75 with a Tron decoder that a hostile site can use to show one transfer and sign another. This is 0.30.0 plus that fix only; 0.31.0 is still under review. --- bundled-addons/aegis/addon.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundled-addons/aegis/addon.json b/bundled-addons/aegis/addon.json index a226cb78..9cb85335 100644 --- a/bundled-addons/aegis/addon.json +++ b/bundled-addons/aegis/addon.json @@ -1,7 +1,7 @@ { "id": "aegis", "name": "Aegis Wallet", - "version": "0.30.0", + "version": "0.30.1", "category": "plugin", "description": "Multi-chain wallet (BCH, BTC, TRX, ETH, SOL, SC, DGB) derived from your Theseus vault. Dapps get window.bitcoincash and window.wizardconnect on any site; window.tronWeb / window.tronLink / window.ethereum / window.solana too. Every call needs your approval.", "author": "Silent Mode",