T09 · Insecure Skill Coding Practices
- Location
scripts/auth.py:61- Finding
API Key Stored Without Restrictive File Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its HS-code lookup purpose, but it handles API keys, payments, update checks, and error reports in ways users should review before installing.
Review this skill before installing. Use it only if you are comfortable with a paid API integration that stores an Upkuajing API key in `~/.upkuajing/.env`, can create recharge links, and can send error diagnostics to the platform after confirmation. Do not run commands that print the API key, and avoid approving error reports unless you can verify the payload contains no secrets or private business data.
scripts/auth.py:61API Key Stored Without Restrictive File Permissions
SKILL.md:37Documentation Instructs the Agent to Print the API Key File
scripts/error_report.py:18Error Reports Can Transmit Unredacted Sensitive Diagnostic Data
requirements.txt:1Unbounded and Unhashed Third-Party Dependency
Version checking, reading skill files, writing cache data under the user's home directory, and emitting upgrade notices are unrelated to the advertised HS-code lookup purpose. These side behaviors create unnecessary filesystem and network activity, which increases privacy and integrity risk while reducing transparency about what the skill actually does.
Version checking, reading skill files, writing cache data under the user's home directory, and emitting upgrade notices are unrelated to the advertised HS-code lookup purpose. These side behaviors create unnecessary filesystem and network activity, which increases privacy and integrity risk while reducing transparency about what the skill actually does.
Version checking, reading skill files, writing cache data under the user's home directory, and emitting upgrade notices are unrelated to the advertised HS-code lookup purpose. These side behaviors create unnecessary filesystem and network activity, which increases privacy and integrity risk while reducing transparency about what the skill actually does.
Version checking, reading skill files, writing cache data under the user's home directory, and emitting upgrade notices are unrelated to the advertised HS-code lookup purpose. These side behaviors create unnecessary filesystem and network activity, which increases privacy and integrity risk while reducing transparency about what the skill actually does.
The skill explicitly instructs reading the contents of ~/.upkuajing/.env with cat, which risks exposing the API key in plaintext to the agent output, logs, or downstream tooling. Credential display is unnecessary for normal operation and materially increases the chance of secret leakage.
本技能需要API密钥。API密钥存储在 ~/.upkuajing/.env 文件中:
cat ~/.upkuajing/.env
文件内容示例:
The workflow instructs the agent to check for a key in a local .env file and potentially participate in adding or auto-saving a new API key there. This normalizes direct credential handling by the skill and increases risk of accidental disclosure, overwrite, or insecure storage of secrets on disk.
### **API密钥未设置**
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
The instructions continue the same pattern of direct credential access and persistence in ~/.upkuajing/.env, including auto-saving newly issued keys. In the context of an agent skill advertised as a data lookup tool, this is more dangerous because users are unlikely to expect secret management behavior and may reveal or store credentials without informed consent.
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
### **账户充值**
This script exposes account-management capabilities such as API key issuance, balance queries, recharge order creation, and pricing lookup that are unrelated to the declared HS-code detail lookup purpose. In a skill context, unjustified extra capabilities expand the attack surface and can enable unauthorized account actions or hidden monetization flows.
The function explicitly handles a local .env file for API key presence, indicating direct credential management in the skill code. Managing secrets through predictable flat files increases the chance of accidental disclosure, insecure permissions, or unintended reuse by other processes.
"""
申请新的 API 密钥。
"""
# 检查是否已存在 .env 文件和 API key
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
Reading the .env file to inspect existing API keys means the skill accesses persisted credentials directly. Direct parsing of local secret files is risky because it normalizes unsafe secret handling and can expose credentials through logs, errors, backups, or compromised local environments.
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
# 读取现有的 .env 文件
try:
with open(env_file, 'r', encoding='utf-8') as f:
content = f.read()
Writing the API key to a .env file stores a long-lived credential in a common plaintext location. Plaintext secret persistence materially raises the risk of credential theft from local users, malware, backups, source-control mistakes, or accidental file sharing.
"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")
The code can create recharge/payment orders even though the skill is described only as an HS-code description lookup tool. Payment-related operations are highly sensitive because they can initiate financial workflows and may be abused for unauthorized charges, phishing-style redirection, or concealed commercial actions.
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'
# 日志开关
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_env_file() -> Dict[str, str]:
"""
从 ~/.upkuajing/.env 文件加载环境变量。
Returns:
环境变量字典
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_env_file() -> Dict[str, str]:
"""
从 ~/.upkuajing/.env 文件加载环境变量。
Returns:
环境变量字典
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_env_file() -> Dict[str, str]:
"""
从 ~/.upkuajing/.env 文件加载环境变量。
Returns:
环境变量字典
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_env_file() -> Dict[str, str]:
"""
从 ~/.upkuajing/.env 文件加载环境变量。
Returns:
环境变量字典
This file implements remote error reporting, which is outside the stated purpose of an HS code detail lookup skill. Hidden auxiliary network behavior increases attack surface and can leak operational data in a context where users would reasonably expect only classification queries, making the mismatch security-relevant even if the code appears intended for telemetry.
The skill declares capabilities that include environment access, local file interaction, and network use, but it does not define any explicit tool scope or allowlist. That makes the effective privilege boundary unclear and increases the chance that an agent could invoke broader operations than users expect, especially around credential files and remote API actions.
The manifest description, headings, trigger phrases, and all usage examples are written exclusively in Chinese and frame the skill as operating in Chinese by default, despite the skill returning both Chinese and English descriptions. There is no stated option for the user to choose language or locale, which can violate the policy against forcing a specific language without user opt-in.
The document instructs agents to send request parameters, response data, and exception context to an error-report API, which can include sensitive business data, identifiers, or stack traces. Although it mentions automatic desensitization, it provides no explicit requirement to minimize data, obtain user/operator awareness, or prohibit secrets/PII in the payload, creating a realistic privacy and data-leakage risk during failure handling.
The module docstring and all user-facing descriptions are written only in Chinese, and the file provides no indication that another language can be selected or that the skill is intentionally limited to Chinese-speaking users. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.
The script can request a new API key and persist it locally, which exceeds the minimal functionality needed for HS-code detail lookup. Credential provisioning inside a content-query skill is dangerous because it may silently bootstrap long-lived access for subsequent misuse or broaden access beyond the user's expectation.
The explicit require_auth=False setting weakens the trust boundary around a sensitive operation that provisions API access. In the context of a simple lookup skill, unauthenticated key issuance is especially unjustified and increases the chance of silent credential bootstrap or backend abuse.
pass # 如果读取失败,继续执行
# 不需要认证申请新密钥
response = make_request('/agent/auth/create', {}, require_auth=False)
# 检查是否申请成功
if response.get('code') != 0:
The explicit require_auth=False setting weakens the trust boundary around a sensitive operation that provisions API access. In the context of a simple lookup skill, unauthenticated key issuance is especially unjustified and increases the chance of silent credential bootstrap or backend abuse.
pass # 如果读取失败,继续执行
# 不需要认证申请新密钥
response = make_request('/agent/auth/create', {}, require_auth=False)
# 检查是否申请成功
if response.get('code') != 0: