T09 · Insecure Skill Coding Practices
- Location
handler.py:176- Finding
Non-HTTPS Webhook URLs Are Accepted for Sensitive Monitoring Events
- Content
View full analysis
Vulnerability Details
File Location:
handler.py, lines 176–203
Vulnerability Type: Insufficient validation of a sensitive-data destination
Risk Level: MediumThe
watch_brandfunction documents that the webhook must use HTTPS, but it only verifies thatwebhook_urlis nonempty. It forwards arbitrary URL values to MentionsAPI when creating a persistent monitor.python if not query or not brand: return {"error": "invalid_argument", "detail": "query and brand are required."} if not webhook_url or not webhook_secret: return { "error": "invalid_argument", "detail": "webhook_url and webhook_secret are required.", } if len(webhook_secret) < 16: return { "error": "invalid_argument", "detail": "webhook_secret must be at least 16 characters.", } return _post( "/v1/watch", { "query": query, "brand": brand, "mode": mode, "interval": interval, "webhook_url": webhook_url, "webhook_secret": webhook_secret, "trigger_on": trigger_on, }, )Technical Analysis
Brand-monitoring events can contain sensitive competitive intelligence, including mention status, rankings, citations, and changes over time. The project documentation therefore requires an HTTPS webhook endpoint. However, the implementation does not parse the URL, verify its scheme, reject embedded credentials, or confirm that it contains a valid hostname.
Consequently, an
http://destination or another malformed or unsupported URL is submitted to the remote API. If MentionsAPI accepts an HTTP destination, subsequent webhook events can travel without transport encryption. HMAC signing only authenticates the message and protects its integrity; it does not provide confidentiality and does not independently prevent replay attacks.The primary API credential is not affected by this issue:
_postsends i ...[truncated 1831 chars]- Remediation
View remediation
Remediation Suggestions
- Parse
webhook_urlwithurllib.parse.urlsplit. - Require the scheme to be exactly
https, using a case-normalized comparison. - Require a nonempty, syntactically valid hostname.
- Reject URLs containing embedded usernames or passwords.
- Reject fragments and unsupported URL forms.
- If MentionsAPI does not support internal destinations, reject loopback, link-local, private, multicast, and otherwise non-public addresses. Apply equivalent checks after DNS resolution to mitigate hostname-based bypasses and DNS rebinding.
- Retain equivalent server-side validation at MentionsAPI so clients cannot bypass the Skill's checks.
- Add tests confirming rejection of
http://, credential-bearing, malformed, loopback, and private-network webhook URLs, along with acceptance of a valid public HTTPS URL. - Continue requiring HMAC signatures and document that receivers must validate the signature, timestamp, and nonce to prevent tampering and replay.
- Provide monitor-management functionality or documentation so users can promptly revoke incorrectly configured persistent monitors and stop recurring charges.
A minimal local validation pattern is:
python from urllib.parse import urlsplit parsed = urlsplit(webhook_url) if ( parsed.scheme.lower() != "https" or not parsed.hostname or parsed.username is not None or parsed.password is not None or parsed.fragment ): return { "error": "invalid_argument", "detail": "webhook_url must be a valid HTTPS URL without credentials or fragments.", }- Parse
