Fix invalid dummy pubkey in send_to_route
What changed, and why it matters
This commit fixes a programming bug in rust-lightning's send_to_route function. When a user supplied a payment route with no paths or an empty first path, the code tried to create a fallback 'dummy' public key using 32 bytes of data, but public keys require 33 bytes. That mismatch caused the program to panic and crash. The fix simply changes the dummy data to 33 bytes so the fallback public key is valid and the unwrap succeeds. It is a denial-of-service/crash bug, not a theft-of-funds vulnerability, because the panic aborts the operation rather than letting an attacker manipulate funds.
Upgrade to a release containing this commit. If running a node that accepts routes from untrusted sources, treat this as a remotely triggerable crash vector and patch promptly. Also audit other uses of PublicKey::from_slice for hardcoded dummy keys to ensure consistent 33-byte lengths.
Security signals we found
panic due to invalid public-key byte length
denial-of-service via malformed route input
unwrap on fallible public-key parsing
API input validation gap
Evidence from the diff
In lightning/src/ln/channelmanager.rs, the send_payment_with_route code constructs fallback RouteParameters when a route has no usable payee hop. It attempts PublicKey::from_slice(&[2; 32]).unwrap() as a dummy payee node id. A secp256k1 compressed public key is 33 bytes, so from_slice returns Err and unwrap() panics. The patch changes the slice to [2; 33], producing a syntactically valid (though arbitrary) compressed public key and avoiding the panic. The bug is reachable only when route.paths is empty or route.paths[0].hops is empty, which is abnormal input rather than normal payment flow.
Changed components
lightning/src/ln/channelmanager.rssend_payment_with_route / send_to_routeRouteParameters construction fallback pathInspect captured patch +1 / −1
diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 2d00b1d..4939226 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -5642,7 +5642,7 @@ impl<
// Create a dummy route params since they're a required parameter but unused in this case
let (payee_node_id, cltv_delta) = route.paths.first()
.and_then(|path| path.hops.last().map(|hop| (hop.pubkey, hop.cltv_expiry_delta as u32)))
- .unwrap_or_else(|| (PublicKey::from_slice(&[2; 32]).unwrap(), MIN_FINAL_CLTV_EXPIRY_DELTA as u32));
+ .unwrap_or_else(|| (PublicKey::from_slice(&[2; 33]).unwrap(), MIN_FINAL_CLTV_EXPIRY_DELTA as u32));
let dummy_payment_params = PaymentParameters::from_node_id(payee_node_id, cltv_delta);
RouteParameters::from_payment_params_and_value(dummy_payment_params, route.get_total_amount())
});
Why this scored 44/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.