T09 · Insecure Skill Coding Practices
- Location
scripts/lcp_node.py:261- Finding
Peer Identity Impersonation Through Self-Asserted Public Keys
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a real peer-to-peer agent messaging skill, but its authentication and local control boundaries are too weak for trusted agent-to-agent use without review.
Install only if you understand that messages cross your Tailnet and are stored on disk. Do not use it for secrets or autonomous task execution until peer key pinning, source validation, authenticated IPC, restrictive key storage, and clearer cleanup/disable steps are added. Avoid enabling auto-start or the Windows service form on shared machines.
scripts/lcp_node.py:261Peer Identity Impersonation Through Self-Asserted Public Keys
scripts/lcp_node.py:251Spoofable and Premature Delivery Acknowledgments
scripts/lcp_crypto.py:16Ed25519 Private Seed Created Without Restrictive File Permissions
scripts/windows/lcp_node_win.py:276Unauthenticated Windows IPC Allows Local Message Disclosure and Impersonation
The skill advertises capabilities that imply file access and shell-driven execution patterns, but it does not declare any explicit tool scope or permission boundaries. In an agent setting, this can cause the host to grant broader-than-necessary access implicitly, increasing the chance of unintended file modification, command execution, or data exposure when the skill is invoked.
The trigger phrases are very broad for a skill that enables cross-machine communication and local daemon control, making accidental or overly frequent activation more likely. That matters because invocation could lead to network transmission, local state changes, and persistence-related setup in contexts where the user did not clearly intend to use a P2P messaging subsystem.
The skill description promotes signed bot-to-bot messaging, local IPC, and storage in inbox/outbox directories, but it does not warn users that content will traverse the network and be persisted locally. Users may provide sensitive data under the assumption of transient local processing, creating confidentiality and retention risks if messages are stored, forwarded, or later accessed by other local processes.
The auto-start guidance instructs users to create a persistent LaunchAgent with RunAtLoad and KeepAlive, which establishes session persistence for a network-capable daemon. While persistence is presented as operational convenience, it increases exposure by keeping the service available continuously and can make unauthorized or unintended communication survive reboots and user logins.
## Auto-start (macOS)
Create a LaunchAgent plist pointing to `lcp_node.py` with `RunAtLoad=true` and `KeepAlive` for crash recovery.
## Auto-start (Windows)
The top-level docstring describes the script as archiving processed inbox messages via LCP daemon IPC, which indicates daemon-mediated behavior. In practice, lines L51-L53 invoke a direct filesystem-based fallback when the IPC socket is unavailable, contradicting the stated execution model rather than merely omitting a minor detail.
The module docstring says it archives processed inbox messages via the LCP daemon IPC and replaces the prior ACK path for UDP mode, implying daemon-mediated control as the mechanism. However, the fallback path directly renames message files in the inbox to the archive directory, so the script performs local filesystem mutation independently of the daemon rather than only using IPC-based acknowledgment.
This code generates and persists an Ed25519 private key to disk in keys/identity.pem, which is a security-sensitive file write affecting local credentials. Although the function has an internal docstring, there is no user-facing prompt, warning, or disclosure at the point of creation to inform users that persistent key material will be stored locally.
The ACK IPC command moves all inbox message files into the archive directory, which changes local user data state, but there is no confirmation prompt or explicit user-facing warning at the point of execution. The surrounding docstrings and logs describe the action only as an internal implementation detail, not as a disclosure to the user invoking the command.
The code persists the Ed25519 private key unencrypted to a predictable path on disk beside the script, with no permission hardening, secure storage API, or operator warning about key sensitivity. In this skill's context, that key is the trust anchor for bot-to-bot message signing, so local theft of the file would let an attacker impersonate the agent and forge authenticated messages across the distributed system.
The local IPC command ACK moves all inbox message files into the archive directory, which changes message state in bulk and may affect user data handling. Although the code executes the operation, there is no confirmation prompt or explicit user-facing warning tied to this destructive state transition.
The code forces timestamps to use UTC+8 via a hard-coded timezone offset when constructing outgoing messages. This imposes a locale-specific behavior without giving the user a choice or documenting why that locale is required.
The UDP listener persists inbound message contents to INBOX_DIR as JSON files, which stores potentially sensitive transmitted data on disk. While logging exists for receipt, there is no visible warning or disclosure to the user in prompts, comments, or documentation within this file that messages will be stored locally.