Back to skill

Security audit

Email Webhook

Security checks for vulnerabilities and agentic risk

Overview

The skill partly matches its email-webhook purpose, but it exposes a public listener, stores full emails, and sends untrusted email text directly to an agent in ways that are not accurately disclosed.

Install only if you are comfortable operating a public HTTPS webhook that stores full email payloads locally and can wake an OpenClaw agent. Use a strong secret, restrict network exposure, rotate or delete the inbox file, avoid placing it in an unusual path, and treat all email sender, subject, and body content as untrusted input that must not authorize agent actions.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T01 · Skill Instruction Hijacking

Error
Location
scripts/webhook_server.js:75
Finding

Untrusted Email Content Is Delivered Directly to the Agent Message Channel

Content
View full analysis
console.error(`[WAKE] Failed: ${err.message}`)); ``` ### Technical Analysis The `from` and `subject` properties originate from the webhook request body and are incorporated directly into a message delivered to an OpenClaw agent. Removing newlines and truncating the message to 200 characters protects neither against natural-language prompt injection nor against content that impersonates trusted operator instructions. Bearer authentication only proves that the requester knows the shared webhook secret. It does not establish that the supplied email fields are safe agent instructions. This is particularly relevant when the webhook producer processes arbitrary Internet email, where an external email sender may control the subject or sender display name without knowing the webhook secret. The implementation also differs from the documented wake mechanism. `SKILL.md` states that the server invokes `openclaw system event --mode now`, while the code invokes `openclaw agent --message ... --deliver`, creating a direct agent-message channel. ### Attack Path 1. An attacker sends an email with a crafted subject or sender display name to an address handled by the authorized webhook producer. 2. The producer submits the resulting email JSON with its valid webhook bearer token. 3. The server extracts the attacker-controlled `from` and `subject` ...[truncated 759 chars]
Remediation
View remediation

other

Note
Location
scripts/webhook_server.js:123
Finding

Undeclared Public-IP Discovery and External Reachability Probe

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/webhook_server.js:48
Finding

Shell Command Construction During Certificate Generation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/webhook_server.js:63
Finding

Large Synchronous Webhook Writes Permit Resource Exhaustion

Content
View full analysis
{ const auth = req.headers['authorization']; if (auth !== `Bearer ${SECRET}`) { console.warn(`[AUTH] Unauthorized attempt from ${req.ip}`); return res.status(403).send('Forbidden'); } const email = req.body; if (!email || typeof email !== 'object') { return res.status(400).send('Invalid payload'); } console.log(`[OK] Email received: ${email.subject || '(no subject)'}`); try { const entry = JSON.stringify({ receivedAt: new Date().toISOString(), ...email }) + '\n'; fs.appendFileSync(INBOX_PATH, entry); ``` ### Technical Analysis The global JSON parser accepts request bodies up to 50 MB. After minimal type checking, the request handler serializes the entire object again and writes it using `fs.appendFileSync()`. Synchronous filesystem operations block Node.js's event loop until the write completes. Repeated large requests can therefore delay all other requests. The inbox file also grows without an enforced quota, retention period, or automatic rotation. The documentation only asks users to delete or rotate it periodically, which does not provide a runtime control. Exploitation requires a valid webhook bearer token or control over an authorized webhook producer. A token compromise, malicious integration, or producer defect could consequently turn this endpoint into a denial-of-service mechanism. ### Attack Path 1. An attacker obtains the shared webhook secret or compromises an authorized webhook producer. 2. The attacker repeatedly sends valid JSON payloads approaching the 50 MB parser limit. 3. Each request is parsed into memory and ser ...[truncated 641 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented purpose understates the skill's actual behavior: it persists email contents locally, exposes a listening server, may generate TLS materials, and appears to perform external network activity beyond simple webhook receipt. This mismatch is dangerous because users may approve or deploy the skill without understanding that it handles sensitive content, opens attack surface, and performs additional privileged actions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill exposes network-facing behavior and depends on environment secrets, but it does not declare an explicit tool scope such as permissions or allowed-tools. That makes its operational capabilities less transparent to users and reviewers, increasing the risk of unintended execution, overbroad access, or unsafe deployment decisions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill uses broad activation language about waking the agent on incoming email without clearly constraining triggers, filtering criteria, or trust boundaries. In context, this can cause unsolicited external input to wake and influence agent behavior, expanding the attack surface for prompt injection, spam-triggered execution, or noisy autonomous actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The setup instructions do not prominently warn users that full email contents and metadata are stored locally and may be relayed through other communication channels. This creates a meaningful privacy and data-handling risk because sensitive emails could be persisted unencrypted, retained indefinitely, or disclosed via cross-channel notifications without informed consent.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The Cloudflare setup guidance is internally inconsistent about port and protocol usage, which can cause operators to expose the service incorrectly or deploy it with weaker-than-expected transport assumptions. Security-sensitive setup ambiguity around HTTP/HTTPS, Flexible SSL, and supported ports can lead to misconfiguration that undermines confidentiality or availability.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes an email webhook receiver that accepts JSON emails and wakes an agent. Invoking OpenSSL via execSync to create local certificates introduces a subprocess-execution capability unrelated to the core email-ingestion purpose, and this is a stronger capability than the manifest suggests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The server appends the full webhook email payload to a local JSONL file without minimization, encryption, retention controls, or prominent disclosure. Incoming email data can contain sensitive personal, business, or authentication content, so storing entire payloads increases confidentiality and compliance risk if the host or file is later accessed.

Content

No source excerpt is available for this finding.

Dynamic Request Target

Medium
Category
Server-Side Request Forgery
Confidence
60% confidence
Finding

Request target host is built from a dynamic or untrusted value. If the host is attacker-influenced, this enables SSRF to arbitrary internal or metadata endpoints.

Content

Scanner excerpt · scripts/webhook_server.js (reported line 128)May include surrounding context.

js
try {
            // Use http (CF Flexible) or https (CF Full) — either way, any response = port open
            await fetch(`https://${ip}:${port}/`, {
                signal: AbortSignal.timeout(6000),
                // ignore self-signed cert error via Node TLS
            });

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/webhook_server.js (reported line 139)May include surrounding context.

js
console.log(`✅ External access OK: port ${port} reachable, TLS handshake succeeded (public IP: ${ip})`);
            } else if (e.name === 'AbortError') {
                console.log(`❌ External access FAILED: port ${port} timed out — likely blocked by firewall (public IP: ${ip})`);
                console.log(`   → Run: sudo ufw allow ${port}/tcp`);
            } else if (e.message.includes('ECONNREFUSED')) {
                console.log(`❌ External access FAILED: connection refused on port ${port} (public IP: ${ip})`);
                console.log(`   → Run: sudo ufw allow ${port}/tcp`);

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/webhook_server.js (reported line 142)May include surrounding context.

js
console.log(`✅ External access OK: port ${port} reachable, TLS handshake succeeded (public IP: ${ip})`);
            } else if (e.name === 'AbortError') {
                console.log(`❌ External access FAILED: port ${port} timed out — likely blocked by firewall (public IP: ${ip})`);
                console.log(`   → Run: sudo ufw allow ${port}/tcp`);
            } else if (e.message.includes('ECONNREFUSED')) {
                console.log(`❌ External access FAILED: connection refused on port ${port} (public IP: ${ip})`);
                console.log(`   → Run: sudo ufw allow ${port}/tcp`);

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

A skill described as receiving incoming email webhooks would be expected to listen for inbound requests, store them, and wake the agent. Querying api.ipify.org and probing the server's own public endpoint are auxiliary diagnostics that add outbound networking capability not clearly justified by the manifest description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

On startup, the code sends a request to api.ipify.org to discover the host's public IP, which transmits network metadata to an external service. Although the result is logged, there is no prior warning that the skill will contact a third-party service for connectivity checks.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/webhook_server.js:51

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/webhook_server.js:10