tx.unsigned: refuse to sign legacy (non-JSON) TX files

Prevent signing of transactions from legacy TX files, which represent a
potential vector for deserialization attacks.

Since a normal up-to-date MMGen Wallet installation cannot create legacy TX
files, it indicates the online installation is compromised or broken, so exit
the signing loop as well and output a critical error message.
This commit is contained in:
The MMGen Project 2026-08-29 15:04:29 +00:00
commit 852cdeda0b
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
6 changed files with 14 additions and 2 deletions

View file

@ -4,6 +4,8 @@ run-name: Build and install
on:
push:
branches:
- ci
paths:
- '.github/workflows/build.yaml'
- '.github/build-requirements.txt'

View file

@ -4,6 +4,8 @@ run-name: Check code with Ruff, Bandit and Pylint static analyzers
on:
push:
branches:
- ci
paths:
- '.github/workflows/lint.yaml'
- '.github/build-requirements.txt'

View file

@ -272,6 +272,8 @@ class Autosign:
except Exception as e:
ymsg('An error occurred with {}{}’:\n {}: ‘{}'.format(
target.desc, f.name, type(e).__name__, e))
if type(e).__name__ == 'LegacyTxSignRequestError':
raise
except:
ymsg('An error occurred with {}{}'.format(target.desc, f.name))
good.append(ret) if ret else bad.append(f)

View file

@ -1 +1 @@
16.2.0
16.3.0dev0

View file

@ -86,6 +86,7 @@ class WalletFileError(Exception): mmcode = 3
class HexadecimalStringError(Exception): mmcode = 3
class SeedLengthError(Exception): mmcode = 3
class PrivateKeyError(Exception): mmcode = 3
class LegacyTxSignRequestError(Exception):mmcode = 3
class MMGenCalledProcessError(Exception): mmcode = 3
class TestSuiteFatalException(Exception): mmcode = 3

View file

@ -13,7 +13,7 @@ tx.unsigned: unsigned transaction class
"""
from .completed import Completed
from ..util import remove_dups
from ..util import die, remove_dups
class Unsigned(Completed):
desc = 'unsigned transaction'
@ -23,6 +23,11 @@ class Unsigned(Completed):
# Return signed object or False. Don’t exit or raise exception, unless fatal:
async def sign(self, keys, tx_num_str=''):
if self.file_format == 'legacy': # fatal
die('LegacyTxSignRequestError',
'Request to sign legacy-format transaction. '
'Has your online installation been compromised?')
try:
self.check_correct_chain()
except Exception as e: