Back to skill

Security audit

Dooray Hook

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a straightforward Dooray webhook sender, but it accepts arbitrary configured webhook destinations and allows disabling TLS verification, which can expose messages or webhook tokens if misconfigured.

Install only if you trust and control the OpenClaw config entry for this skill. Keep verify_ssl set to true, store only genuine Dooray webhook URLs, protect the config file permissions, and rotate any webhook token that may have been used with TLS verification disabled or placed in an untrusted config.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_dooray.py:104
Finding
Unrestricted Webhook Destination Enables Arbitrary Outbound Requests## Vulnerability Details **File Location**: `scripts/send_dooray.py:104-130` **Vulnerability Type**: Missing destination validation / server-side request forgery **Risk Level**: Medium ### Vulnerable Code ```python webhook_url = rooms[room_name] bot_name = dooray_config.get("botName", "OpenClaw") bot_icon = dooray_config.get("botIconImage", "https://static.dooray.com/static_images/dooray-bot.png") # Check for SSL verification override (Default: True) verify_ssl = dooray_config.get("verify_ssl", True) # Prepare payload payload = { "botName": bot_name, "botIconImage": bot_icon, "text": message_text } payload_json = json.dumps(payload).encode('utf-8') # Send POST request try: req = urllib.request.Request( webhook_url, data=payload_json, headers={ 'Content-Type': 'application/json', 'User-Agent': 'OpenClaw-Dooray-Skill/1.0' }, method='POST' ) ``` ### Technical Analysis The script obtains the destination URL directly from the global OpenClaw configuration and passes it to `urllib.request.Request` without validating its scheme, hostname, port, path, or resolved address. The declared functionality only requires access to Dooray incoming webhook URLs in the form `https://hook.dooray.com/services/{TOKEN}`. Accepting arbitrary destinations exceeds that minimum network scope. Although `references/dooray-api.md` recommends URL validation, the implementation does not enforce the documented format. If an attacker can alter the configuration, or if a user is induced to add a malicious room definition, the process can be made to send a POST request to an attacker-controlled server or a network service reachable from the host. The transmitted JSON includes the caller-provided message, configured bot name, and configured icon URL. ### Attack Path 1. An attacker gains the ability to modify, influence, or sociall ...[truncated 1360 chars]
Remediation
## Remediation Suggestions 1. Parse each configured URL with `urllib.parse.urlsplit`. 2. Require the scheme to be exactly `https`. 3. Require the normalized hostname to be exactly `hook.dooray.com`. 4. Require the path to begin with `/services/` and contain a nonempty token. 5. Reject embedded user information, fragments, unexpected ports, malformed URLs, and control characters. 6. Prevent redirects to destinations outside the same approved HTTPS origin, or disable automatic redirects for webhook requests. 7. If deployment-specific Dooray domains must be supported, use an explicit administrator-controlled hostname allowlist rather than accepting arbitrary URLs. 8. Consider rejecting loopback, link-local, private, and reserved resolved addresses as defense in depth. 9. Validate all configured rooms at startup and fail closed before transmitting any message. 10. Add tests covering external domains, HTTP URLs, user-information confusion, alternate ports, malformed paths, and cross-host redirects.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_dooray.py:138
Finding
Configurable TLS Verification Bypass Exposes Webhook Credentials and Messages## Vulnerability Details **File Location**: `scripts/send_dooray.py:109, 138-147` **Vulnerability Type**: Improper certificate validation **Risk Level**: Medium ### Vulnerable Code ```python # Check for SSL verification override (Default: True) verify_ssl = dooray_config.get("verify_ssl", True) ``` ```python # [SECURITY] Conditional SSL Context if verify_ssl: # Secure default: Validates SSL certificates ssl_context = ssl.create_default_context() else: # Insecure opt-in: Ignores certificate errors (for proxies/self-signed certs) # This handles the [SSL: CERTIFICATE_VERIFY_FAILED] error if config allows it. ssl_context = ssl._create_unverified_context() with urllib.request.urlopen(req, timeout=10, context=ssl_context) as response: ``` ### Technical Analysis TLS certificate verification is enabled by default, but the `verify_ssl` configuration option can completely disable certificate and hostname authentication by selecting `ssl._create_unverified_context()`. When verification is disabled, TLS encryption does not authenticate the remote endpoint. An active network attacker, malicious proxy, or compromised network device can present an arbitrary certificate and impersonate the webhook server. This is especially sensitive because the Dooray webhook token is embedded in the request URL and functions as the credential for posting to the associated room. Both that credential and the message payload become available to a successful interceptor. The insecure option is documented in `SKILL.md` as a workaround for certificate failures. This increases the chance that users will disable verification persistently rather than install the appropriate trusted certificate authority. ### Attack Path 1. The user or administrator sets `"verify_ssl": false`, potentially to work around a corporate proxy or self-signed certificate. 2. The Skill sends a message while connected through a hostile or compr ...[truncated 1146 chars]
Remediation
## Remediation Suggestions 1. Remove support for `ssl._create_unverified_context()` and always verify server certificates and hostnames. 2. Replace `verify_ssl` with an optional CA-bundle setting for private or corporate certificate authorities. 3. Construct the context with `ssl.create_default_context(cafile=approved_ca_path)` when a custom CA is required. 4. Validate that any configured CA file is an administrator-controlled regular file with restrictive permissions. 5. Fail closed on certificate errors instead of recommending that users disable verification. 6. Update `SKILL.md` to document installation of the corporate CA or configuration of an approved CA bundle. 7. Rotate affected webhook tokens if messages have previously been transmitted with certificate verification disabled over an untrusted network. 8. Add tests confirming that self-signed, expired, hostname-mismatched, and untrusted certificates are rejected.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding
The skill documentation describes capabilities that read a local configuration file and send data over the network, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization gap: an agent may invoke file-read and outbound network actions without a clear least-privilege contract, increasing the risk of unintended secret access or exfiltration if the skill is misused or extended.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
To use this skill, you must define your Dooray! webhook URLs in the OpenClaw global config (`~/.openclaw/openclaw.json`).

> **Security Note:** Webhook URLs are stored in your local config file. Ensure this file's permissions are restricted (e.g., `chmod 600`).

```json
{
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
## Example Requests

### cURL Example

```bash
curl -X POST https://hook.dooray.com/services/YOUR_TOKEN \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
The text explicitly labels the official documentation as Korean, but does not offer an alternative language option or explain that the resource is region/language-specific. This can violate language/locale policy expectations when users are not given an opt-in or choice.

Intent-Code Divergence

Low
Confidence
82% confidence
Finding
The module docstring presents the implementation scope as only using standard-library dependencies, which suggests a self-contained utility. In reality, the script depends on side-effectful external state in ~/.openclaw/openclaw.json, and the load_config docstring confirms that hidden dependency. This is an intent/documentation mismatch, not merely an omitted implementation detail, because the usage text does not disclose that configuration prerequisite.

Static analysis

No suspicious patterns detected.