T09 · Insecure Skill Coding Practices
- Location
invoice-discern.py:14- Finding
Unrestricted API Endpoint Allows Disclosure of Credentials and Invoice Data
- Content
View full analysis
Vulnerability Details
File Location:
invoice-discern.py, lines 14–25 and 33–62
Vulnerability Type: Unvalidated destination URL for sensitive network requests
Risk Level: HighVulnerable Code
python def get_token(api_url, ak, sk, type_value): """获取访问令牌""" token_url = f"{api_url}/api/v2/agent/common/cdk/getToken" secret_string = get_md5(ak + sk) payload = { "akString": ak, "secretString": secret_string, "type": int(type_value), "forceUpdate": 0 } try: response = requests.post(token_url, json=payload) result = response.json() if result.get("code") == "200": return result["data"] else: return None, result.get("message", "获取Token失败") except Exception as e: return None, str(e)python def discern_invoice(file_path, tax_no=None): """识别发票""" api_url = os.getenv("HSY_API_URL", "https://huisuiyun.com") ak = os.getenv("HSY_AK") sk = os.getenv("HSY_SK") type_value = os.getenv("HSY_TYPE", "2") # ... headers = {"X-Access-Token": token} if type_value == "1" and tax_no: headers["X-Tax-Token"] = tax_no discern_url = f"{api_url}/api/v2/agent/cdk/invoice/discern" try: with open(file_path, 'rb') as f: files = {'file': f} response = requests.post(discern_url, files=files, headers=headers) return response.json() except Exception as e: return {"error": str(e)}Technical Analysis
The destination for both authentication and invoice-upload requests is controlled through the
HSY_API_URLenvironment variable. The implementation concatenates API paths onto this value without validating its scheme, hostname, port, user-information component, or final destination.Consequently, the value may point to an arbitrary HTTP or HTTPS ...[truncated 3298 chars]
- Remediation
View remediation
Remediation Suggestions
-
Pin the production API origin. Use a constant such as
https://huisuiyun.comrather than accepting an unrestricted environment-provided URL.python API_ORIGIN = "https://huisuiyun.com" -
If endpoint configurability is operationally necessary, enforce an explicit allowlist. Parse the URL and require:
- The
httpsscheme. - An exact approved hostname.
- No username or password component.
- No fragments.
- Only an approved port, normally
443.
python from urllib.parse import urlparse ALLOWED_HOSTS = {"huisuiyun.com"} def validate_api_url(value): parsed = urlparse(value) if ( parsed.scheme != "https" or parsed.hostname not in ALLOWED_HOSTS or parsed.username is not None or parsed.password is not None or parsed.port not in (None, 443) or parsed.fragment ): raise ValueError("Unapproved HSY API endpoint") return f"https://{parsed.hostname}" - The
-
Do not silently permit development endpoints in production. If testing against alternate servers is required, place that capability behind an explicit development-only option and use a separate set of non-production credentials.
-
Set connection and response timeouts on both requests to limit denial-of-service exposure:
python response = requests.post(token_url, json=payload, timeout=(5, 30)) response.raise_for_status() -
Validate authentication responses strictly. Confirm the HTTP status, response content type, expected JSON structure, and token type before using the returned value.
-
Avoid redirecting sensitive requests to unapproved origins. Disable redirects or validate every redirect destination before forwarding credentials or invoice data:
python requests.post(..., allow_redirects=False)
...[truncated 555 chars]
-
