T09 · Insecure Skill Coding Practices
- Location
scripts/send_mail.py:25- Finding
API Credentials and Email Content Can Be Transmitted over Plaintext HTTP
- Content
View full analysis
Vulnerability Details
File Location:
scripts/send_mail.py:25-54; also affectsscripts/check_credential.py:22-32
Vulnerability Type: Missing enforcement of encrypted transport
Risk Level: HighVulnerable Code
python base_url = _require_env("UNIPROFIT_API_BASE_URL").rstrip("/") api_key = _require_env("UNIPROFIT_MAIL_SEND_KEY") body = json.dumps( { "account_id": args.account_id, "to_email": args.to_email, "to_name": args.to_name or None, "subject": args.subject, "body": args.body, "reply_to": args.reply_to or None, }, ensure_ascii=False, ).encode("utf-8") req = urllib.request.Request( f"{base_url}/openclaw/mail/send", data=body, headers={ "Content-Type": "application/json", "X-UniProfit-Key": api_key, }, method="POST", ) try: with urllib.request.urlopen(req, timeout=30) as resp:The credential-checking script uses the same unvalidated base URL:
python base_url = _require_env("UNIPROFIT_API_BASE_URL").rstrip("/") api_key = _require_env(KEY_ENV) req = urllib.request.Request( f"{base_url}/openclaw/credential/me", headers={"X-UniProfit-Key": api_key}, method="GET", ) try: with urllib.request.urlopen(req, timeout=20) as resp:Technical Analysis
Both scripts accept
UNIPROFIT_API_BASE_URLdirectly from the environment and pass it tourllib.request.urlopenwithout parsing the URL or requiring thehttpsscheme. Although the documentation provides an HTTPS example, the implementation does not enforce that requirement.If the configured URL uses
http://, theX-UniProfit-Keycredential is transmitted without transport encryption. The mail-sending request additionally exposes the sender account identifier, recipient address, recipient name, subject, complete message body, and reply-to address.Because the host i ...[truncated 1545 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse
UNIPROFIT_API_BASE_URLwithurllib.parse.urlsplit. - Reject every scheme other than
https. - If local HTTP development is necessary, permit it only behind an explicit development option and only for loopback addresses such as
127.0.0.1or::1. - Require a nonempty hostname and reject URLs containing embedded user information, fragments, or unexpected path components.
- Where deployments have a fixed service destination, enforce an administrator-controlled hostname allowlist.
- Apply the same centralized URL validation to both scripts before constructing any authenticated request.
- Rotate the API key if it may previously have been sent to an HTTP or untrusted endpoint.
- Retain normal TLS certificate and hostname validation; do not introduce an unverified SSL context.
Example validation:
python from urllib.parse import urlsplit def _validate_base_url(value: str) -> str: value = value.rstrip("/") parsed = urlsplit(value) if parsed.scheme != "https": raise SystemExit("UNIPROFIT_API_BASE_URL must use HTTPS") if not parsed.hostname or parsed.username or parsed.password: raise SystemExit("Invalid UNIPROFIT_API_BASE_URL") return value- Parse
