lsp_plugin: add sane error to listprotocols
What changed, and why it matters
This commit improves error handling in a Core Lightning plugin's list-protocols feature. It replaces a programming panic (an abrupt crash) with proper error messages when something goes wrong, and adds clearer logging. There is no direct evidence this fixes an exploitable security vulnerability, but it does make the plugin more robust and easier to diagnose.
No urgent action required. Treat as routine hardening. If auditing, verify no other unwrap() calls in the plugin handle attacker-controlled input without graceful error handling.
Security signals we found
Replaced unwrap() on user-controlled JSON deserialization with anyhow context-based error propagation
Added error context around transport creation and RPC call
Added debug logging for RPC responses
Evidence from the diff
The patch modifies plugins/lsps-plugin/src/client.rs for the lsps-listprotocols RPC handler. It replaces an unwrap() on serde_json::from_value with anyhow’s context() for graceful error propagation, splits transport construction from client creation to attach error context, and adds a debug! log of the response. These are defensive hardening changes rather than a clear security fix.
Changed components
plugins/lsps-plugin/src/client.rslsps-listprotocols RPC handlerInspect captured patch +19 / −6
diff --git a/plugins/lsps-plugin/src/client.rs b/plugins/lsps-plugin/src/client.rs
index c54699c6..92b5a9e1 100644
--- a/plugins/lsps-plugin/src/client.rs
+++ b/plugins/lsps-plugin/src/client.rs
@@ -1,8 +1,10 @@
+use anyhow::Context;
use cln_lsps::jsonrpc::client::JsonRpcClient;
use cln_lsps::lsps0::{
self,
transport::{Bolt8Transport, CustomMessageHookManager, WithCustomMessageHookManager},
};
+use log::debug;
use serde::Deserialize;
use std::path::Path;
@@ -38,6 +40,7 @@ async fn main() -> Result<(), anyhow::Error> {
}
}
+/// RPC Method handler for `lsps-listprotocols`.
async fn on_lsps_listprotocols(
p: cln_plugin::Plugin<State>,
v: serde_json::Value,
@@ -49,16 +52,26 @@ async fn on_lsps_listprotocols(
let dir = p.configuration().lightning_dir;
let rpc_path = Path::new(&dir).join(&p.configuration().rpc_file);
- let req: Request = serde_json::from_value(v).unwrap();
+ let req: Request = serde_json::from_value(v).context("Failed to parse request JSON")?;
- let client = JsonRpcClient::new(Bolt8Transport::new(
+ // Create the transport first and handle potential errors
+ let transport = Bolt8Transport::new(
&req.peer,
rpc_path,
p.state().hook_manager.clone(),
- None,
- )?);
+ None, // Use default timeout
+ )
+ .context("Failed to create Bolt8Transport")?;
+
+ // Now create the client using the transport
+ let client = JsonRpcClient::new(transport);
+
+ let request = lsps0::model::Lsps0listProtocolsRequest {};
let res: lsps0::model::Lsps0listProtocolsResponse = client
- .call_typed(lsps0::model::Lsps0listProtocolsRequest {})
- .await?;
+ .call_typed(request)
+ .await
+ .context("lsps0.list_protocols call failed")?;
+
+ debug!("Received lsps0.list_protocols response: {:?}", res);
Ok(serde_json::to_value(res)?)
}
Why this scored 18/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.