Back to skill

Security audit

agent-link-local-agent

Security checks for vulnerabilities and agentic risk

Overview

This skill is a relay-based agent messaging client, but its security claims are stronger than the code and examples support.

Review before installing. Use only with a relay you control or trust, prefer wss:// with valid TLS, avoid sending sensitive content unless you add end-to-end encryption, store the shared secret outside shell history and world-readable files, and treat inbound Agent messages as untrusted unless the client is updated to verify signatures and prevent replay.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/local-agent/agent_link.py:121
Finding
Inbound Relay Messages Are Accepted Without Authentication<![CDATA[ ## Vulnerability Details **File Location**: `scripts/local-agent/agent_link.py`, lines 121–151 **Vulnerability Type**: Missing message signature verification **Risk Level**: High ### Vulnerable Code ```python if msg_type == "message": from_agent = data.get("from") to_agent = data.get("to") message = data.get("message") msg = Message( from_agent=from_agent, to_agent=to_agent, message=message, timestamp=datetime.now() ) logger.info(f"Received message from {from_agent}: {message[:50]}...") # 调用消息处理器 full_to = f"{self.instance_id}/{self.agent_id}" if to_agent == full_to or to_agent == self.agent_id: for handler in self.message_handlers.values(): try: handler(msg) except Exception as e: logger.error(f"Message handler error: {e}") ``` ### Technical Analysis The client signs outbound messages using HMAC-SHA256, but the inbound message-processing path does not retrieve or verify a signature. It also does not validate a trusted timestamp, nonce, sequence number, or other replay-protection value. Consequently, the values in the `from`, `to`, and `message` fields are treated as authentic solely because they arrived through the currently connected relay. A malicious or compromised relay can therefore assign an arbitrary sender identity and deliver attacker-controlled content to local message handlers. This behavior contradicts the documentation's claim that messages are signed and verified. Transport authentication alone would not fully resolve this issue because the relay itself remains capable of forging messages unless messages are authenticated end to end. ### Attack Path 1. An attacker compromises, impersonates, or operates the configured relay server. 2. The victim client connects and completes the relay's expected registration exchange. 3. The attacker sends a WebSocket frame such as: ```json { "type": ...[truncated 1126 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require every inbound application message to contain a signature generated by the originating instance. 2. Sign a canonical representation containing, at minimum: - Protocol version and message type - Sender and recipient - Message content - Creation timestamp - Cryptographically random nonce or monotonically increasing sequence number 3. Recompute the expected HMAC locally and compare it with `hmac.compare_digest()` rather than ordinary string comparison. 4. Reject missing, malformed, invalid, or stale signatures before constructing the `Message` object or calling handlers. 5. Store recently accepted nonces or sequence numbers and reject duplicates to prevent replay attacks. 6. Use distinct per-instance or per-Agent keys rather than one global shared secret. Alternatively, use asymmetric signatures so a relay can route messages without gaining the ability to forge them. 7. Apply strict schema and size validation to all incoming JSON fields. 8. Add tests demonstrating rejection of forged senders, modified content, stale timestamps, duplicate nonces, and missing signatures. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/local-agent/agent-link-config.example.json:1
Finding
Plaintext WebSocket Transport Is Used in the Default Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/local-agent/agent-link-config.example.json`, lines 1–9 **Additional Locations**: `SKILL.md`, lines 96 and 132; `README.md`, line 167; `docs/install-agent.md`, lines 39 and 68 **Vulnerability Type**: Unencrypted network transport **Risk Level**: High ### Vulnerable Code ```json { "relay_url": "ws://your-relay-server:8765", "secret": "your-secret-key-here-change-this", "instance_id": "instance-001", "agent_id": "healthguard", "auto_reconnect": true, "reconnect_interval": 5, "log_level": "INFO" } ``` The client accepts this URL without enforcing secure transport: ```python logger.info(f"Connecting to relay server: {self.relay_url}") self.websocket = await websockets.connect(self.relay_url) ``` ### Technical Analysis The example configuration and installation documentation direct users to connect using `ws://`, which provides no TLS encryption or server certificate authentication. HMAC signatures do not encrypt message content, sender identifiers, recipient identifiers, or other metadata. Moreover, the registration exchange accepts a relay response based only on its JSON `type`; the client has no independent server identity check when plaintext WebSockets are used. This permits an on-path attacker to observe communication and potentially impersonate the relay. The insecure defaults conflict with the documentation's separate assertion that communication uses WSS. ### Attack Path 1. A user copies the supplied example and replaces only the relay hostname, leaving the `ws://` scheme intact. 2. The client establishes an unencrypted WebSocket connection over an untrusted or shared network. 3. An on-path attacker captures message content, sender and recipient identifiers, and protocol exchanges. 4. The attacker can redirect, terminate, or impersonate the relay connection because the client receives no TLS-authenticated server identity. 5. A forged relay can return a `registered` resp ...[truncated 591 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change every example and installation command to use `wss://`. 2. Reject `ws://` URLs by default in the client. If plaintext transport is needed for local development, require an explicit unsafe-development option and restrict it to loopback addresses. 3. Deploy the relay with a valid TLS certificate whose hostname matches the configured relay hostname. 4. Retain the `websockets` library's certificate and hostname validation; do not introduce an unverified SSL context. 5. Consider certificate or public-key pinning where clients connect to a privately operated, stable relay. 6. Continue to implement end-to-end message authentication because TLS protects only the client-to-relay channel and does not prevent a malicious relay from forging application messages. 7. Add startup validation that produces a clear error when a non-secure URL is configured. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/local-agent/agent_link.py:230
Finding
Shared Secret Can Be Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/local-agent/agent_link.py`, lines 230–247 **Additional Location**: `SKILL.md`, lines 88 and 96 **Vulnerability Type**: Insecure secret handling **Risk Level**: Medium ### Vulnerable Code The client explicitly accepts the shared secret as a command-line argument: ```python parser.add_argument("--secret", type=str, help="Shared secret key") ``` It then uses that argument to construct the client: ```python if not all([args.relay_url, args.secret, args.instance_id, args.agent_id]): print("Error: --config or --relay-url/--secret/--instance-id/--agent-id required") return client = AgentLink( relay_url=args.relay_url, secret=args.secret, instance_id=args.instance_id, agent_id=args.agent_id ) ``` The documentation encourages this practice: ```bash python3 relay_server.py --port 8765 --secret "your-secret-key" ``` ```bash python3 setup.py --relay-url "ws://your-relay-server:8765" --secret "your-secret-key" ``` ### Technical Analysis Command-line arguments are commonly retained in shell history and may be visible in process listings, process-monitoring systems, audit logs, diagnostic reports, or orchestration metadata. Quoting a secret prevents shell word splitting but does not conceal the value from these channels. The documented design uses a shared secret across the relay and local Agents. Exposure of that secret can therefore affect more than the single process in which it was supplied. One of the documented commands references an absent `setup.py`, and the relay implementation is not included in the audited artifact. Nevertheless, the included client does implement `--secret`, so the local exposure path is directly present. ### Attack Path 1. An operator starts the client using `--secret real-production-secret`, as supported by the implementation. 2. The command is stored in shell history or exposed in process metadata while the process is running. 3. A local use ...[truncated 874 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove or deprecate the `--secret` command-line option. 2. Load secrets from one of the following: - A dedicated secret manager - An operating-system credential store - A permission-restricted configuration file - An environment variable supplied through a protected runtime facility - An interactive no-echo prompt for manual use 3. If configuration files are supported, verify restrictive file permissions and fail or warn when the file is readable by unintended users. 4. Use separate credentials for each instance or Agent so one disclosure does not compromise the entire deployment. 5. Establish key rotation and revocation procedures. 6. Redact secrets from exceptions, logs, diagnostics, and configuration displays. 7. Replace all documentation examples that place secrets directly on a command line. ]]>

T08 · Insecure Dependencies

Warning
Location
docs/install-agent.md:24
Finding
Third-Party WebSocket Dependency Is Installed Without Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `docs/install-agent.md`, line 24 **Additional Location**: `README.md`, lines 32 and 41 **Vulnerability Type**: Unpinned third-party dependency **Risk Level**: Medium ### Vulnerable Code ```bash pip install websockets ``` ### Technical Analysis The installation instructions request whichever version of the `websockets` package the package index resolves at installation time. The project supplies no lock file, exact version constraint, package hash, or documented trusted index. This makes installations non-reproducible and prevents consumers from confirming that they are installing the same dependency version that was reviewed and tested by the project author. A future compromised release, unsafe update, or incompatible version can consequently enter the runtime without a project code change. No evidence in the audited artifact shows that the named package is currently malicious. The risk arises from unconstrained and unverified dependency retrieval. ### Attack Path 1. A user follows the documented `pip install websockets` command. 2. `pip` resolves the currently available package version from its configured index or mirror. 3. If that release or package source has been compromised, malicious installation or runtime code is downloaded without a hash mismatch or lock-file failure. 4. The dependency executes in the Python environment during installation or when imported by `agent_link.py`. 5. The malicious dependency gains the privileges of the user running the installation or Agent process. ### Impact Assessment A compromised dependency can execute arbitrary Python code with the installing user's privileges. This may permit access to the Agent's configuration, shared secret, messages, files accessible to the process, and network connections. The scope is limited by the operating-system privileges and environment of the user performing installation or running the client. Installing as an administra ...[truncated 48 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the dependency to an exact reviewed version in a requirements file or lock file. 2. Record and enforce package hashes, for example with `pip install --require-hashes -r requirements.txt`. 3. Document the approved package index and avoid untrusted mirrors. 4. Test dependency upgrades explicitly before changing the pinned version. 5. Use automated dependency vulnerability scanning and update alerts. 6. Install dependencies in an isolated virtual environment under a non-privileged account. 7. Publish reproducible installation instructions that reference the committed lock or requirements file rather than an unconstrained package name. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (8)

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README explicitly promotes using a public relay server for agent-to-agent messaging and even shows a default `ws://` configuration later, but it does not clearly warn that message contents transit a third-party endpoint and are exposed to interception if TLS is not used. Because readers may follow the quick-start as written, this documentation can lead to insecure deployment and confidentiality loss for agent messages or metadata.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The quick-start and config examples encourage passing a shared secret directly on the command line and storing it in plaintext config files. Command-line arguments are often exposed through shell history, process listings, logs, and orchestration tooling, which can leak the credential and allow unauthorized agents or servers to impersonate trusted peers.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The manifest description is written entirely in Chinese and provides no indication that the skill supports other languages or that the locale restriction is intentional. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the constraint is clearly documented and justified.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code establishes a WebSocket connection to a relay server and immediately sends a registration payload containing instance metadata. Although there are developer-oriented log messages, there is no user disclosure or confirmation that data will be transmitted off-host, which matters because network/HTTP-style transmission is safety-relevant for code files.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
该文档从标题开始即以中文呈现,后续示例命令和说明也默认面向中文读者,没有提供用户可选择的语言/locale 选项,也未说明这是特定中文用户群体专用文档。按照语言/locale 政策,这属于未显式提供用户选择的语言限定。

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The module docstring and many user/developer-facing comments are written in Chinese, while the file does not indicate that the tool is intentionally region-specific or provide any language selection. This can violate language/locale policy when a skill implicitly fixes one language without opt-in or justification.

Missing User Warnings

Low
Confidence
78% confidence
Finding
The code loads a JSON config file and retrieves a secret value used for authentication, but provides no user-facing notice that sensitive credentials are being read from disk. Comments and docstrings are implementation-focused and do not warn users about secret handling or advise secure storage practices.

Static analysis

No suspicious patterns detected.