Back to skill

Security audit

Agent Relay

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent phone relay, but it lets remote messages and attachments trigger powerful agent actions with weak trust boundaries.

Review before installing. Use this only with a locked-down dedicated agent, authenticated webhook sender validation, strict attachment URL and size limits, and explicit cleanup. Do not expose the recommended hook publicly as written or run relay-originated turns with unrestricted shell, filesystem, memory, or network tools.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T01 · Skill Instruction Hijacking

Error
Location
references/hooks-config.md:52
Finding

Public Webhook Requests Can Become Privileged Full-Agent Turns

Content
View full analysis
", "path": "/hooks", "defaultSessionKey": "hook:relay", "allowRequestSessionKey": false, "allowedAgentIds": ["main"], "allowedSessionKeyPrefixes": ["hook:"], "transformsDir": "/.openclaw/hooks/transforms", "mappings": [ { "id": "agent-relay", "match": { "path": "agent-relay" }, "action": "agent", "agentId": "main", "wakeMode": "now", "name": "Agent Relay", "sessionKey": "hook:relay", "messageTemplate": "--- Message from User via Relay ({{message.id}}) ---\n{{message.text}}\n--- End relay ---\n\nProcess this as a full agent turn. Reply with:\n relay send \"\"\n\nETIQUETTE: Short (1-3 lines), direct, no fluff, no sign-offs.", "deliver": false, "transform": { "module": "agent-relay.mjs" } } ] } } ``` ```nginx handle /hooks/* { reverse_proxy localhost:18789 { header_up Authorization "Bearer " } } ``` ```js return { message: [ `--- Message from User via Relay (${msg.id || ""}) ---`, parts.join("\n"), "--- End relay ---", "", "Process this as a full agent turn. Reply via:", ' /skills/agent-relay/scripts/relay send ""', "", "ETIQUETTE: Short (1-3 lines), direct, no fluff, no sign-offs.", ].join("\n"), }; ``` ### Technical Analysis The recommended reverse-proxy configuration overwrites the `Authorization` header with a valid hook bearer token for every request under `/hooks/*`. Authentication therefore proves only that the request passe ...[truncated 2055 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/transform.mjs:57
Finding

Webhook-Controlled Attachment URL Enables Server-Side Request Forgery

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/transform.mjs:63
Finding

Unbounded Attachment Buffering and Storage Enables Denial of Service

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/poll-inbox-fallback:33
Finding

Environment-Controlled Values Are Injected into Dynamically Generated Python Source

Content
View full analysis
/dev/null || true ``` The polling-only variant contains the same unsafe source-generation pattern: ```bash echo "$RESP" | python3 -c " import json, sys messages = json.load(sys.stdin) for msg in messages: mid = msg.get('id', '') text = msg.get('text', '') att = msg.get('attachment') created = msg.get('createdAt', '') print(f'--- Message from User via Relay ({mid}) ---') print(text) if att: print(f'Attachment: {att.get(\"name\",\"\")} ({att.get(\"type\",\"\")})') print(f'URL: {att.get(\"url\",\"\")}') print('Download the attachment to inspect it.') print('--- End relay ---') print() # Save last seen ID if messages: with open('$LAST_SEEN', 'w') as f: f.write(messages[-1].get('id', '')) ...[truncated 2330 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (13)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 133)May include surrounding context.

md
| `SKILL.md` | This document |

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill explicitly instructs the agent to use local transforms, cron jobs, shell-based scripts, and file inspection of downloaded attachments, but it does not declare any tool scope such as allowed-tools or permissions. This creates a privilege ambiguity where an installer may enable the skill without realizing it expects shell and file-write capabilities, increasing the risk of over-privileged execution and misuse if untrusted message content or attachments are processed.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 45)May include surrounding context.

md
Deploy to Replit (or any Node.js host):
- Fork the Agent Relay server repo
- Create an agent in the app → get your API key
- Save the key — it's shown only once

### 2. Install the Skill

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 77)May include surrounding context.

md
## Inbox fallback (recommended)

Even with push webhooks working, set up inbox polling as a fallback.
Add a cron job that runs `scripts/poll-inbox-fallback` every 2 minutes.
Failed webhook deliveries are retried by the relay server, then if still failing,
left in the inbox for the fallback poller to catch.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/hooks-config.md (reported line 74)May include surrounding context.

md
## Inbox fallback (recommended)

Even with push webhooks working, set up inbox polling as a fallback.
Add a cron job that runs `scripts/poll-inbox-fallback` every 2 minutes.
Failed webhook deliveries are retried by the relay server, then if still failing,
left in the inbox for the fallback poller to catch.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code fetches an attachment from a remote URL and writes it to a local path, which affects local user data and filesystem state. While the file header explains setup, it does not warn users that incoming attachments will be automatically downloaded and saved locally, and there is no confirmation prompt or user-facing disclosure at the point of action.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · relay (reported line 19)May include surrounding context.

text
fi

do_whoami() {
  curl -sf "$BASE_URL/relay/whoami" \
    -H "Authorization: Bearer $API_KEY"
}

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/relay (reported line 30)May include surrounding context.

text
fi

do_whoami() {
  curl -sf "$BASE_URL/relay/whoami" \
    -H "Authorization: Bearer $API_KEY"
}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script sends user-provided text, titles, and bodies to remote relay endpoints via curl, but there is no confirmation prompt, visible print/log message, or explanatory comment warning that this content is transmitted off-host. For a code file, these network transmissions qualify as safety-relevant behavior that should have some explicit disclosure unless already clearly warned elsewhere.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script retrieves arbitrary inbox content from a remote service and prints it directly for downstream agent consumption with no trust boundary marking, sanitization, or warning that the data is untrusted. In an agent skill context, this is dangerous because message text and attachment metadata can contain prompt-injection instructions or socially engineered content that may influence later automated processing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The send and attachment functions perform HTTP POST requests carrying user-supplied text and attachment metadata to an external service. Although the header comments describe setup and usage, the script itself provides no runtime disclosure or confirmation that user content will be transmitted off-system.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The notify function sends title and body fields via an HTTP POST request to the Relay service. The file lacks a visible warning in the operational flow or help output that notification contents are transmitted externally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The script retrieves an API key and base URL from the password store, which is access to sensitive credentials, but the only note is a terse comment and an error on missing credentials. There is no user-facing disclosure or warning that the tool reads stored secrets to authenticate against the relay service.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.