T09 · Insecure Skill Coding Practices
- Location
scripts/loan_check.py:10- Finding
Sensitive Financial Data and Authentication Token Transmitted over Plaintext HTTP
- Content
View full analysis
Vulnerability Details
File Location:
scripts/loan_check.py, lines 10–11, 14–24, and 82–94
Vulnerability Type: Cleartext transmission of sensitive information
Risk Level: HighVulnerable Code
python API_BASE = os.environ.get(f"COZE_LOAN_CHECK_API_URL_{SKILL_ID}", os.environ.get("LOAN_CHECK_API_URL", "http://47.109.39.255:8765/api/v4") USER_KEY = os.environ.get("LOAN_CHECK_USER_KEY", "") def api_call(endpoint, data=None, method="POST"): url = f"{API_BASE.rstrip('/')}/{endpoint}" h = {"Content-Type": "application/json"} if USER_KEY: h["X-User-Key"] = USER_KEY try: if method == "GET": resp = requests.get(url, headers=h, params=data or {}, timeout=30) else: resp = requests.post(url, headers=h, json=data or {}, timeout=60)The loan-assessment operation supplies sensitive customer information to this API call:
python def cmd_check(args): if not USER_KEY: print("❌ 请先设置 LOAN_CHECK_USER_KEY 环境变量", file=sys.stderr) print(" 注册命令:脚本 register --username 你的名字", file=sys.stderr) sys.exit(1) print(f"🚀 贷款资质预审中...", file=sys.stderr) data = {} data['age'] = args.age data['income'] = args.income if args.credit: data['credit'] = args.credit if args.loan_type: data['loan_type'] = args.loan_type data['loan_amount'] = args.loan_amount if args.loan_amount else 10 if args.city: data['city'] = args.city result = api_call("loan-check", data)Technical Analysis
The default API endpoint uses unencrypted HTTP:
text http://47.109.39.255:8765/api/v4The client places the user's authentication credential in the
X-User-Keyheader and sends applicant information—including age, income, credit status, requested loan amount, loan type, and city—in the request body. HTTP provides neither transport confidentiality nor cryptographic server authentication.An attacker with a suitable network position can inspect the r ...[truncated 1964 chars]
- Remediation
View remediation
Remediation Suggestions
- Replace the plaintext default endpoint with an HTTPS URL on an operator-controlled hostname that has a valid TLS certificate.
- Reject insecure endpoint configurations before sending any request:
python from urllib.parse import urlparse parsed = urlparse(API_BASE) if parsed.scheme != "https": raise RuntimeError("LOAN_CHECK_API_URL must use HTTPS")- Do not provide an HTTP fallback. Fail closed when a secure endpoint has not been configured.
- Retain TLS certificate and hostname verification; do not introduce
verify=Falseor custom logic that bypasses certificate validation. - Rotate user keys that may already have traversed plaintext networks and provide a revocation mechanism for compromised keys.
- Apply least privilege and expiration to API keys, rate-limit their use, and monitor for replay or anomalous consumption.
- Minimize submitted applicant data to fields strictly required for an assessment.
- Clearly disclose the remote recipient, purpose, retention period, and handling policy for financial information before transmission.
- Consider application-level encryption for especially sensitive fields in addition to mandatory TLS where the service's threat model requires it.
- Add automated tests that reject
http://API URLs and verify that credentials are transmitted only through authenticated TLS connections.
