msggen: fix primitive serialization for special names
What changed, and why it matters
This is a small code-generator bug fix. The tool that automatically creates Rust data structures from message definitions was using the wrong internal name when deciding whether to apply a special Serde rename annotation. As a result, fields whose original JSON name is a Rust reserved word (like 'type') were not being renamed correctly in the generated code. The patch corrects the generator and updates one generated struct so the field serializes as 'type' in JSON again. It is a correctness/serialization fix, not an obvious security vulnerability.
Treat as a routine bug fix. If deploying a release that includes this change, verify that any downstream tools relying on the generated Rust RPC models for fields named 'type' (or other Rust reserved words) now produce the expected JSON. No emergency response is warranted based on the diff alone.
Security signals we found
Generated RPC serialization code was producing incorrect JSON field names for schema fields that collide with Rust reserved words.
Incorrect serialization of 'type' field in network events could break API consumers or cause type confusion in downstream parsing.
No explicit security claim, exploit primitive, or trust boundary crossing is present in the diff.
Evidence from the diff
In contrib/msggen/msggen/gen/rpc/rust.py, gen_primitive() was calling rename_if_necessary(org, p.name.name) instead of rename_if_necessary(org, p.name.normalized()). The .name attribute is the raw schema name, while .normalized() is the Rust-safe identifier (e.g., ‘type’ becomes ‘item_type’). Because the comparison was between the raw name and the normalized name, the rename check always saw them as different and emitted a #[serde(rename = …)] annotation even when it shouldn’t, or conversely failed to emit the rename when the raw name was a Rust keyword. The regenerated cln-rpc/src/model.rs shows the concrete effect: ListnetworkeventsNetworkevents now has #[serde(rename = “type”)] on item_type, ensuring the struct field serializes to the JSON key ‘type’. Without this, RPC clients using the generated Rust model could serialize/deserialize the wrong JSON key for fields that are Rust reserved words.
Changed components
contrib/msggen/msggen/gen/rpc/rust.pycln-rpc/src/model.rsGenerated Rust RPC client models for Core LightningInspect captured patch +3 / −2
diff --git a/cln-rpc/src/model.rs b/cln-rpc/src/model.rs
index 7d616d90..e6c4b3a9 100644
--- a/cln-rpc/src/model.rs
+++ b/cln-rpc/src/model.rs
@@ -12462,6 +12462,8 @@ pub mod responses {
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ListnetworkeventsNetworkevents {
+ #[serde(rename = "type")]
+ pub item_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub connect_attempted: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -12469,7 +12471,6 @@ pub mod responses {
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
pub created_index: u64,
- pub item_type: String,
pub peer_id: PublicKey,
pub timestamp: u64,
}
diff --git a/contrib/msggen/msggen/gen/rpc/rust.py b/contrib/msggen/msggen/gen/rpc/rust.py
index 556b495b..14beeae6 100644
--- a/contrib/msggen/msggen/gen/rpc/rust.py
+++ b/contrib/msggen/msggen/gen/rpc/rust.py
@@ -209,7 +209,7 @@ def gen_primitive(p):
if p.deprecated:
defi += " #[deprecated]\n"
- defi += rename_if_necessary(org, p.name.name)
+ defi += rename_if_necessary(org, p.name.normalized())
if not p.optional:
defi += f" pub {p.name.normalized()}: {typename},\n"
else:
Why this scored 16/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.