T09 · Insecure Skill Coding Practices
- Location
scripts/generate_xhs.py:68- Finding
Unvalidated API Endpoint Can Expose Credentials and Local Document Content
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate_xhs.py:68-79andscripts/generate_xhs.py:99
Vulnerability Type: Unrestricted destination and transport for sensitive network transmission
Risk Level: MediumVulnerable Code
python headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } url = base_url.rstrip('/') + "/chat/completions" payload = { "model": model_name, "messages": [ {"role": "system", "content": "You are a professional social media manager specializing in Xiaohongshu (XHS). Output in Chinese language."}, {"role": "user", "content": prompt} ], "temperature": 0.7 } try: response = requests.post(url, headers=headers, json=payload, timeout=60)The endpoint is populated directly from an environment variable:
python BASE_URL = os.getenv("LLM_BASE_URL") or "https://api.openai.com/v1"Technical Analysis
The script allows
LLM_BASE_URLto control the destination of an outbound request without validating its scheme or hostname. The request contains two sensitive data classes:- The LLM API credential in the
Authorizationheader. - Content read from user-selected source files and optional publishing history in the request body.
Although the documented default uses HTTPS, the implementation accepts arbitrary values, including plaintext
http://endpoints and attacker-controlled hosts. This conflicts with the documentation's assurance that local content is transmitted through encrypted HTTPS.The outbound LLM request is necessary for the declared content-generation functionality. However, accepting an unrestricted destination and insecure transport exceeds the minimum network privilege required. An HTTPS-only restriction is appropriate for remote providers. If local HTTP inference endpoints must be supported, they should require explicit opt-in and must not receive production API credentials.
Attack Path
- A ...[truncated 1523 chars]
- The LLM API credential in the
- Remediation
View remediation
Remediation Suggestions
- Parse
LLM_BASE_URLwithurllib.parse.urlparseand reject malformed URLs. - Require the
httpsscheme for all remote endpoints. - Reject URLs containing embedded usernames or passwords.
- Maintain an optional allowlist of approved provider hostnames, or require explicit user confirmation before sending data to a non-default hostname.
- Disable automatic redirects or validate every redirect destination, ensuring redirects cannot downgrade HTTPS or move sensitive requests to an unapproved host.
- If localhost HTTP endpoints are required for tools such as Ollama, allow only loopback addresses through an explicit opt-in setting and avoid sending an API key when authentication is unnecessary.
- Display the resolved destination hostname and clearly warn the user that selected source and history content will be transmitted before the first request.
- Update the security documentation so its transport guarantees exactly match the enforced implementation.
Example validation logic:
python from urllib.parse import urlparse def validate_base_url(base_url): parsed = urlparse(base_url) if parsed.scheme != "https": raise ValueError("LLM_BASE_URL must use HTTPS") if not parsed.hostname: raise ValueError("LLM_BASE_URL must contain a valid hostname") if parsed.username or parsed.password: raise ValueError("Embedded URL credentials are not allowed") return base_url.rstrip("/")Use the validated value to construct the endpoint, and configure redirect handling conservatively:
python validated_base_url = validate_base_url(base_url) url = validated_base_url + "/chat/completions" response = requests.post( url, headers=headers, json=payload, timeout=60, allow_redirects=False, )- Parse
