Skip to content

Gate identity learning on signature in NodeDB::updateUser - #11084

Merged
caveman99 merged 1 commit into
developfrom
nodeinfo-identity-gate
Jul 20, 2026
Merged

Gate identity learning on signature in NodeDB::updateUser#11084
caveman99 merged 1 commit into
developfrom
nodeinfo-identity-gate

Conversation

@caveman99

@caveman99 caveman99 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Problem

NodeInfoModule gated its unsigned-signer check on isBroadcast(mp.to), so the unicast path reached nodeDB->updateUser without the same scrutiny. The public-key comparison in updateUser is not sufficient on its own here.

Same shape as the case already handled in TrafficManagementModule, applied to the primary NodeInfo path.

Fix

Gated inside NodeDB::updateUser, the single chokepoint for identity learning. It takes a new xeddsaSigned parameter and skips the identity write when the stored node has the signer bit and the update is unsigned:

if (nodeId != getNodeNum() && nodeInfoLiteHasXeddsaSigned(info) && !xeddsaSigned) {
    LOG_WARN("Refusing unsigned identity update for node 0x%08x that previously signed", nodeId);
    return false;
}

Notes on the design:

  • Unicast NodeInfo is not dropped. Only the identity write is skipped, so legitimate signer exchanges keep working.
  • The parameter defaults to false, so any unaudited or future caller fails closed.
  • Self-updates are exempt via nodeId != getNodeNum(), which keeps MeshService::reloadOwner working unchanged.
  • The check reads the stored info before CopyUserToNodeInfoLite overwrites it, so it tests the stored signer bit rather than the incoming one.

Callers now pass mp.xeddsa_signed. The existing unauthenticatedSigner guard in TrafficManagementModule is now redundant (its path is only reached for non-signers) but was left in place.

Tests

Added to test_packet_signing group C:

  • C5 unsigned unicast NodeInfo from a signer: packet accepted, stored name unchanged.
  • C6 the same exchange signed: name updates. Pins C5 as a targeted skip rather than a blanket block on unicast NodeInfo.
  • C7 unsigned unicast from a non-signer: name updates, ordinary mesh traffic unaffected.

test_packet_signing 34/34, plus test_fuzz_packets, test_traffic_management, test_nodedb_blocked, test_type_conversions 93/93 on native-windows.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented unsigned identity updates from overwriting stored names for nodes known to use XEdDSA signing.
    • Signed identity updates continue to apply normally.
    • Unsigned updates from nodes without a known signing history remain supported.
  • Tests

    • Added coverage for signed and unsigned identity-update scenarios.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: daf94b71-5457-46ae-8330-8cb8a69aeef3

📥 Commits

Reviewing files that changed from the base of the PR and between 375e1fc and 20c5706.

📒 Files selected for processing (5)
  • src/mesh/NodeDB.cpp
  • src/mesh/NodeDB.h
  • src/modules/NodeInfoModule.cpp
  • src/modules/TrafficManagementModule.cpp
  • test/test_packet_signing/test_main.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/modules/NodeInfoModule.cpp
  • src/modules/TrafficManagementModule.cpp
  • src/mesh/NodeDB.h

📝 Walkthrough

Walkthrough

NodeDB::updateUser now receives XEdDSA signer status and blocks unsigned identity updates for nodes previously marked as signers. NodeInfo call sites pass this status, and packet-signing tests cover signer and non-signer unicast behavior.

Changes

Signer-aware identity updates

Layer / File(s) Summary
Signer-aware update contract and callers
src/mesh/NodeDB.h, src/modules/NodeInfoModule.cpp, src/modules/TrafficManagementModule.cpp
updateUser accepts an xeddsaSigned flag, and NodeInfo-related callers pass the packet’s XEdDSA signing status.
Identity guard and behavioral coverage
src/mesh/NodeDB.cpp, test/test_packet_signing/test_main.cpp
Known XEdDSA signers reject unsigned identity rewrites; tests verify unsigned, signed, and non-signer unicast updates.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NodeInfoModule
  participant TrafficManagementModule
  participant NodeDB
  NodeInfoModule->>NodeDB: Pass NodeInfo identity and xeddsa_signed
  TrafficManagementModule->>NodeDB: Pass direct-response identity and xeddsa_signed
  NodeDB->>NodeDB: Allow or reject identity update based on signer state
Loading

Possibly related PRs

Suggested labels: bugfix

Suggested reviewers: thebentern, jp-bennett

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: gating identity learning in NodeDB::updateUser based on signature state.
Description check ✅ Passed The description covers the problem, fix, design notes, and tests, so it is mostly complete despite not matching the template verbatim.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nodeinfo-identity-gate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

NodeInfoModule gated its unsigned-signer check on isBroadcast, so the unicast path reached
updateUser without the same scrutiny. The public-key comparison in updateUser is not
sufficient on its own here. Same shape as the case already handled in
TrafficManagementModule, applied to the primary NodeInfo path.

updateUser now takes xeddsaSigned and skips the identity write when the stored node has the
signer bit and the update is unsigned. The packet is still accepted, so unicast signer
exchanges keep working. Defaults to false so callers fail closed. Self-updates are exempt.

Tests: C5 unsigned unicast from a signer does not change the stored name, C6 the signed
case still does, C7 non-signers are unaffected.
@caveman99
caveman99 force-pushed the nodeinfo-identity-gate branch from 375e1fc to 20c5706 Compare July 20, 2026 08:33
@github-actions

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Note

Building this pull request… the flash button, badges and supported-board
list will appear here automatically once CI finishes.

@caveman99 caveman99 added the bugfix Pull request that fixes bugs label Jul 20, 2026
@caveman99
caveman99 merged commit 5ded0ec into develop Jul 20, 2026
79 of 101 checks passed
@caveman99
caveman99 deleted the nodeinfo-identity-gate branch July 20, 2026 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Pull request that fixes bugs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant