Skip to content

Commit fc7be85

Browse files
authored
Merge pull request #4560 from vincenzopalazzo/claude/nostalgic-merkle
Validate HTTPS scheme in LSPS5 URL Readable deserialization
2 parents ed02087 + 78df66d commit fc7be85

2 files changed

Lines changed: 64 additions & 4 deletions

File tree

lightning-liquidity/src/lsps5/msgs.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,11 @@ impl Writeable for LSPS5WebhookUrl {
457457

458458
impl Readable for LSPS5WebhookUrl {
459459
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
460-
Ok(Self(Readable::read(reader)?))
460+
let url: LSPSUrl = Readable::read(reader)?;
461+
if url.url().len() > MAX_WEBHOOK_URL_LENGTH {
462+
return Err(DecodeError::InvalidValue);
463+
}
464+
Ok(Self(url))
461465
}
462466
}
463467

@@ -902,6 +906,58 @@ mod tests {
902906
}
903907
}
904908

909+
#[test]
910+
fn test_lsps_url_readable_rejects_http() {
911+
use lightning::util::ser::Writeable;
912+
913+
let raw =
914+
lightning_types::string::UntrustedString("http://example.com/webhook".to_string());
915+
let encoded = raw.encode();
916+
let result = LSPSUrl::read(&mut lightning::io::Cursor::new(&encoded));
917+
assert!(result.is_err(), "LSPSUrl::Readable should reject http:// URLs");
918+
}
919+
920+
#[test]
921+
fn test_lsps_url_readable_accepts_https() {
922+
use lightning::util::ser::Writeable;
923+
924+
let https_url = LSPSUrl::parse("https://example.com/webhook".to_string()).unwrap();
925+
let encoded = https_url.encode();
926+
let decoded = LSPSUrl::read(&mut lightning::io::Cursor::new(&encoded)).unwrap();
927+
assert_eq!(decoded.url(), "https://example.com/webhook");
928+
}
929+
930+
#[test]
931+
fn test_webhook_url_readable_rejects_http() {
932+
use lightning::util::ser::Writeable;
933+
934+
let raw =
935+
lightning_types::string::UntrustedString("http://example.com/webhook".to_string());
936+
let encoded = raw.encode();
937+
let result = LSPS5WebhookUrl::read(&mut lightning::io::Cursor::new(&encoded));
938+
assert!(result.is_err(), "Readable should reject http:// webhook URLs");
939+
}
940+
941+
#[test]
942+
fn test_webhook_url_readable_rejects_too_long() {
943+
use lightning::util::ser::Writeable;
944+
945+
let long_url = LSPSUrl::parse(format!("https://example.com/{}", "a".repeat(2000))).unwrap();
946+
let encoded = long_url.encode();
947+
let result = LSPS5WebhookUrl::read(&mut lightning::io::Cursor::new(&encoded));
948+
assert!(result.is_err(), "Readable should reject URLs exceeding MAX_WEBHOOK_URL_LENGTH");
949+
}
950+
951+
#[test]
952+
fn test_webhook_url_readable_accepts_valid_https() {
953+
use lightning::util::ser::Writeable;
954+
955+
let valid_url = LSPS5WebhookUrl::new("https://example.com/webhook".to_string()).unwrap();
956+
let encoded = valid_url.encode();
957+
let decoded = LSPS5WebhookUrl::read(&mut lightning::io::Cursor::new(&encoded)).unwrap();
958+
assert_eq!(decoded.as_str(), "https://example.com/webhook");
959+
}
960+
905961
#[test]
906962
fn test_webhook_notification_parameter_binding() {
907963
let notification = WebhookNotification::expiry_soon(144);

lightning-liquidity/src/lsps5/url_utils.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,12 @@ impl LSPSUrl {
6969
Ok(LSPSUrl(UntrustedString(url_str)))
7070
}
7171

72-
/// Returns URL length.
72+
/// Returns URL length in bytes.
73+
///
74+
/// Since [`LSPSUrl::parse`] only accepts ASCII characters, this is equivalent
75+
/// to the character count.
7376
pub fn url_length(&self) -> usize {
74-
self.0 .0.chars().count()
77+
self.0 .0.len()
7578
}
7679

7780
/// Returns the full URL string.
@@ -99,6 +102,7 @@ impl Writeable for LSPSUrl {
99102

100103
impl Readable for LSPSUrl {
101104
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
102-
Ok(Self(Readable::read(reader)?))
105+
let s: UntrustedString = Readable::read(reader)?;
106+
Self::parse(s.0).map_err(|_| DecodeError::InvalidValue)
103107
}
104108
}

0 commit comments

Comments
 (0)