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.
