T09 · Insecure Skill Coding Practices
- Location
scripts/auth.py:62- Finding
API Key Stored Without Explicitly Restrictive File Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This phone-validation skill is coherent and disclosed overall, but users should understand it uses a paid external API and stores an API key locally.
Install only if you are comfortable sending phone numbers and WhatsApp-status checks to Upkuajing's API and using a paid account. Prefer setting UPKUAJING_API_KEY through a secure environment or secrets manager; if using ~/.upkuajing/.env, restrict its permissions and avoid putting customer records or tokens into error reports.
scripts/auth.py:62API Key Stored Without Explicitly Restrictive File Permissions
requirements.txt:1Third-Party Dependency Uses an Unbounded Minimum-Version Constraint
The skill performs update/version checks, reads SKILL.md metadata, and writes version-cache files in the user's home directory without describing this behavior in its purpose statement. Undisclosed remote update checks and local persistence can surprise users and introduce privacy or integrity concerns.
The skill performs update/version checks, reads SKILL.md metadata, and writes version-cache files in the user's home directory without describing this behavior in its purpose statement. Undisclosed remote update checks and local persistence can surprise users and introduce privacy or integrity concerns.
The skill performs update/version checks, reads SKILL.md metadata, and writes version-cache files in the user's home directory without describing this behavior in its purpose statement. Undisclosed remote update checks and local persistence can surprise users and introduce privacy or integrity concerns.
The skill performs update/version checks, reads SKILL.md metadata, and writes version-cache files in the user's home directory without describing this behavior in its purpose statement. Undisclosed remote update checks and local persistence can surprise users and introduce privacy or integrity concerns.
The skill explicitly instructs access to a credential file in the user's home directory and manual handling of an API key. Any skill that reads or guides storage of secrets in local files has credential-exposure risk, especially when combined with file and network capabilities.
### **API Key Not Set**
First check if the `~/.upkuajing/.env` file has UPKUAJING_API_KEY;
If UPKUAJING_API_KEY is not set, prompt the user to choose:
1. User has one: User provides it (manually add to ~/.upkuajing/.env file)
2. User doesn't have one: Guide user to apply at [Open Platform](https://developer.upkuajing.com/)
Wait for user selection;
This file implements account creation, balance lookup, recharge-order creation, and pricing retrieval, which materially exceed the declared phone/WhatsApp validation purpose. In an agent-skill ecosystem, capability mismatch is dangerous because users may invoke a seemingly harmless data-validation skill that also provisions external accounts and payment workflows, increasing the chance of unauthorized billing, data exposure, or hidden platform lock-in.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
申请新的 API 密钥。
"""
# 检查是否已存在 .env 文件和 API key
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
申请新的 API 密钥。
"""
# 检查是否已存在 .env 文件和 API key
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
申请新的 API 密钥。
"""
# 检查是否已存在 .env 文件和 API key
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
申请新的 API 密钥。
"""
# 检查是否已存在 .env 文件和 API key
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
申请新的 API 密钥。
"""
# 检查是否已存在 .env 文件和 API key
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
申请新的 API 密钥。
"""
# 检查是否已存在 .env 文件和 API key
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
Writing a newly issued API key into a .env file in the user's home directory creates a persistent local secret store without any visible permission hardening. If the file is created with overly broad default permissions or later read by other tooling, the API key could be exposed and abused for unauthorized API access or billing-related actions.
"envFilePath": str(env_file)
}
# 保存到 .env 文件
try:
with open(env_file, 'w', encoding='utf-8') as f:
f.write(f"{API_KEY_ENV}={api_key}\n")
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
API_BASE_URL = "https://openapi.upkuajing.com"
API_KEY_ENV = "UPKUAJING_API_KEY"
UPKUAJING_DIR = Path.home() / '.upkuajing'
UPKUAJING_ENV_FILE = UPKUAJING_DIR / '.env'
UPKUAJING_LOGS_DIR = UPKUAJING_DIR / 'logs'
# 日志开关
The manifest describes a skill for verifying phone numbers and WhatsApp registration status, but this file implements exception telemetry that reports runtime errors to a platform endpoint. That operational behavior is not part of validating phone numbers or cleansing contact data, and represents functionality outside the user-facing scope described in the manifest.
The skill declares no explicit tool scope even though it clearly requires environment-variable access, local file access, and network access. Without a narrow allowlist, an agent runtime may grant broader capabilities than users expect, increasing the chance of unintended file reads/writes or external requests.
The trigger list contains broad phrases such as CRM cleansing and supplier verification, which could cause the skill to be invoked in situations beyond a narrow phone-validation task. Over-broad invocation increases the chance that sensitive workflows or data are routed through this skill unnecessarily.
The documentation describes sending phone numbers and a bearer authorization token, but provides no privacy, storage, masking, retention, or transport-security guidance. Because phone numbers are personal data and bearer tokens grant direct API access, this omission can lead to insecure handling, accidental logging, overexposure in downstream systems, or misuse of sensitive contact data during CRM cleansing and WhatsApp-status checks.
The documentation explicitly permits sending request parameters, response data, and exception context to a platform error-reporting API, which can include phone numbers, WhatsApp status results, CRM data, stack traces, and other sensitive business or personal information. Although it notes that sensitive fields are 'automatically masked,' it does not define masking scope, require minimization, or warn users about third-party transmission, creating a real privacy and data-exposure risk in the context of contact-validation workflows.
All user-facing natural-language strings in the file, including the module description, CLI help text, errors, and success messages, are exclusively in Chinese. The policy requires avoiding a forced language or locale unless the skill offers user choice or clearly documents a justified locale restriction, which is not present here.
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
pass # 如果读取失败,继续执行
# 不需要认证申请新密钥
response = make_request('/agent/auth/create', {}, require_auth=False)
# 检查是否申请成功
if response.get('code') != 0:
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
pass # 如果读取失败,继续执行
# 不需要认证申请新密钥
response = make_request('/agent/auth/create', {}, require_auth=False)
# 检查是否申请成功
if response.get('code') != 0:
Recharge-order and pricing functions are unrelated to validating phone numbers and WhatsApp status, so their presence expands the attack and abuse surface without clear justification. A user or upstream agent expecting contact verification could be induced into unintended commercial actions such as balance inquiries, pricing calls, or generating payment URLs.
This file loads credentials from process environment and from ~/.upkuajing/.env to authenticate outbound API calls. While network access for phone validation is expected, local credential harvesting from user-scoped configuration is a separate capability that is not disclosed in the manifest description or triggers.
The request/response logging functions can persist full API parameters and returned data to ~/.upkuajing/logs when logging is enabled. For a phone-validation skill, those payloads may contain phone numbers, WhatsApp status, account metadata, and possibly authentication-adjacent information, creating local sensitive-data exposure without minimization or user warning at the write site.
Detected: suspicious.exposed_secret_literal