lnpeer: use INVALID_ONION_VERSION for unparsable onions
What changed, and why it matters
This commit tightens how Electrum's Lightning code reports a failed onion packet. Previously it used a generic 'BADONION' flag; now it uses the more specific 'INVALID_ONION_VERSION' code when telling the peer the onion could not be parsed. The change is mainly about following the Lightning specification more precisely and is unlikely to be a security fix for an exploitable bug.
Treat as a normal protocol-correctness patch. Review related Lightning spec compliance if auditing, but no urgent security response is indicated by this commit alone.
Security signals we found
Lightning protocol compliance change for malformed-onion failure codes
No buffer overflow, memory corruption, or authentication bypass visible in diff
No explicit vulnerability disclosure or CVE referenced in commit or materials
Evidence from the diff
In electrum/lnpeer.py, when an incoming HTLC’s onion packet cannot be parsed, the code raises OnionParsingError. Previously this error was constructed with OnionFailureCodeMetaFlag.BADONION. The patch moves the failure code into OnionParsingError itself, setting it to OnionFailureCode.INVALID_ONION_VERSION (BADONION | PERM | 4). The same code is also reused for the TEST_FAIL_HTLCS_AS_MALFORMED debug path. This aligns the update_fail_malformed_htlc error code with BOLT 4, which does not define a plain BADONION code for update_fail_malformed_htlc.
Changed components
electrum/lnpeer.pyelectrum/lnonion.pyLightning onion routing failure handlingInspect captured patch +10 / −4
diff --git a/electrum/lnonion.py b/electrum/lnonion.py
index b57c047..7760fd4 100644
--- a/electrum/lnonion.py
+++ b/electrum/lnonion.py
@@ -577,7 +577,14 @@ class OnionRoutingFailure(Exception):
return error_bytes
-class OnionParsingError(OnionRoutingFailure): pass
+class OnionParsingError(OnionRoutingFailure):
+ """
+ Onion parsing error will cause a htlc to get failed with update_fail_malformed_htlc.
+ Using INVALID_ONION_VERSION as there is no unspecific BADONION failure code defined in the spec
+ for the case we just cannot parse the onion.
+ """
+ def __init__(self, data: bytes):
+ OnionRoutingFailure.__init__(self, code=OnionFailureCode.INVALID_ONION_VERSION, data=data)
def construct_onion_error(
diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
index e263da1..1e8da55 100644
--- a/electrum/lnpeer.py
+++ b/electrum/lnpeer.py
@@ -3229,7 +3229,6 @@ class Peer(Logger, EventListener):
except Exception as parsing_exc:
self.logger.warning(f"unable to parse onion: {str(parsing_exc)}")
onion_parsing_error = OnionParsingError(
- code=OnionFailureCodeMetaFlag.BADONION,
data=sha256(onion_packet_bytes or b''),
)
raise onion_parsing_error
@@ -3259,9 +3258,9 @@ class Peer(Logger, EventListener):
raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_HMAC, data=onion_hash)
except Exception as e:
self.logger.warning(f"error processing onion packet: {e!r}")
- raise OnionParsingError(code=OnionFailureCodeMetaFlag.BADONION, data=onion_hash)
+ raise OnionParsingError(data=onion_hash)
if self.network.config.TEST_FAIL_HTLCS_AS_MALFORMED:
- raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_VERSION, data=onion_hash)
+ raise OnionParsingError(data=onion_hash)
if self.network.config.TEST_FAIL_HTLCS_WITH_TEMP_NODE_FAILURE:
raise OnionRoutingFailure(code=OnionFailureCode.TEMPORARY_NODE_FAILURE, data=b'')
return processed_onion
Why this scored 29/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.