T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/lcp_node.py:261
- Finding
- Peer Identity Impersonation Through Self-Asserted Public Keys<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lcp_crypto.py:48-64`, `scripts/lcp_node.py:261-294`, `scripts/windows/lcp_crypto_win.py:49-64`, and `scripts/windows/lcp_node_win.py:241-263` **Vulnerability Type**: Missing peer-key authentication **Risk Level**: High ### Vulnerable Code ```python def verify_message(msg_dict): """Verify the signature in the security block""" if "security" not in msg_dict: raise ValueError("Missing security block") sec = msg_dict["security"] if sec.get("algo") != "ed25519": raise ValueError(f"Unsupported algorithm: {sec.get('algo')}") pubkey_bytes = base64.b64decode(sec["pubkey"]) sig_bytes = base64.b64decode(sec["signature"]) payload = _canonicalize(msg_dict) verify_key = VerifyKey(pubkey_bytes) try: verify_key.verify(payload, sig_bytes) return True except BadSignatureError: return False ``` The verified message is subsequently stored without checking whether the embedded key belongs to the configured peer: ```python elif msg_type == MSG_DATA: # 1. ACK immediately udp_send_raw(pack(MSG_ACK, seq), addr[0]) # 2. Parse JSON try: msg = json.loads(payload.decode('utf-8')) except json.JSONDecodeError: log.warning(f"Invalid JSON from {addr}") continue msg_id = msg.get("id", "") # 3. Duplicate check if is_seen(msg_id): log.info(f"Duplicate msg {msg_id[:8]}, skipped") continue # 4. Verify signature try: if not verify_message(msg): log.warning(f"Invalid signature from {addr}") continue except Exception as e: log.warning(f"Signature check error: {e}") continue # 5. Save to inbox mark_seen(msg_id) fname = f"msg_{msg_id[:8]}.json" fpath = os.path.join(INBOX_DIR, fname) with open(fpath, 'w', encoding='utf-8') as f: json.dump(msg, f, ensure_ascii=False, inden ...[truncated 2467 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Provision or configure the expected Ed25519 public key for each peer. 2. Compare `security.pubkey` against the pinned key before signature verification and reject unknown or changed keys. 3. If pre-provisioning is unavailable, implement an explicit trust-on-first-use registry with visible key fingerprints and protected persistent storage. 4. Require the UDP source address to match the configured peer address. Treat this only as defense in depth, not as a substitute for cryptographic identity. 5. Validate that the authenticated key is authorized for the signed `from` identity. 6. Require the `to` field to identify the local node. 7. Consider moving the public key out of individual messages and using a configured key identifier. 8. Add negative tests proving that a correctly signed message from an unknown key is rejected. ]]>
