T09 · Insecure Skill Coding Practices
- Location
SKILL.md:37- Finding
Credential File Is Explicitly Printed to Terminal Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill mostly matches its paid trade-data purpose, but it asks users to expose and store an API key in risky ways and includes account, payment, telemetry, and update-check behavior that users should review carefully.
Install only if you are comfortable with a paid third-party API skill that stores an API key under `~/.upkuajing`. Do not run or allow `cat ~/.upkuajing/.env`; provide credentials through a safer environment mechanism where possible, confirm every chargeable or recharge action separately, and avoid sending sensitive request or response data in error reports.
SKILL.md:37Credential File Is Explicitly Printed to Terminal Output
scripts/auth.py:71API Key Is Persisted Without Enforced Restrictive Permissions
requirements.txt:1Dependency Version Is Not Safely Bounded or Reproducibly Pinned
Version checking against a remote API and local cache file management are unrelated to the advertised trade-statistics function. While often legitimate, undisclosed update checks introduce extra network and filesystem behavior that can surprise users, expand telemetry exposure, and create another externally influenced code path.
Version checking against a remote API and local cache file management are unrelated to the advertised trade-statistics function. While often legitimate, undisclosed update checks introduce extra network and filesystem behavior that can surprise users, expand telemetry exposure, and create another externally influenced code path.
Version checking against a remote API and local cache file management are unrelated to the advertised trade-statistics function. While often legitimate, undisclosed update checks introduce extra network and filesystem behavior that can surprise users, expand telemetry exposure, and create another externally influenced code path.
Version checking against a remote API and local cache file management are unrelated to the advertised trade-statistics function. While often legitimate, undisclosed update checks introduce extra network and filesystem behavior that can surprise users, expand telemetry exposure, and create another externally influenced code path.
The documentation explicitly instructs reading the local .env file that stores the API key. Directly accessing secret files increases the chance of credential exposure through logs, terminal output, model observation, or accidental disclosure, and this risk is amplified because the skill already performs network and billing-related actions.
本技能需要API密钥。API密钥存储在 ~/.upkuajing/.env 文件中:
cat ~/.upkuajing/.env
文件内容示例:
The skill workflow includes checking for a local API key in a .env file and guiding users to add or auto-save the key there. Handling secrets through local plaintext files may be common, but it remains risky in agent contexts because other tools, logs, or prompts may expose those contents and because the same credential can authorize billable actions.
### **API密钥未设置**
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
The instructions continue to center local .env inspection and modification for credential management, reinforcing a pattern of direct secret-file interaction. In this context, the danger is elevated because the skill also supports account creation, recharge, and external reporting, so compromise of the key can lead to financial abuse and data exposure.
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
### **账户充值**
This skill is described as a country trade list query utility, but the file implements unrelated account-management functions: API key issuance, account balance lookup, recharge order creation, and pricing queries. That capability expansion increases attack surface and can trigger sensitive side effects unrelated to the declared user task, making the skill more dangerous in context because users and reviewers would not expect financial/account operations inside a data-query skill.
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():
Opening the .env file for writing is part of persisting a live API key in plaintext on disk. In context, this creates a real credential-exposure risk because the skill is unrelated to auth management, users may not expect local secret storage, and plaintext files are easy to leak through backups, logs, or repo commits.
"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 exposes a recharge-order creation action in a skill whose declared purpose is paginated national trade data lookup. Creating payment orders is a sensitive side effect that could be abused to trick users into initiating purchases or to redirect them into unexpected financial flows, and it is especially suspicious because the functionality is out of scope for this skill's business context.
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 querying paginated country trade-list data for market analysis, but this file implements exception reporting to a platform endpoint instead of trade-data retrieval or analysis. While telemetry can be an internal support function, this behavior is materially different from the user-declared skill purpose and is not described in the manifest.
The skill declares capabilities that involve environment access, local file access, and network activity, but it does not define any explicit tool scope or permission boundary. That creates unnecessary ambiguity about what the skill may do at runtime and weakens least-privilege controls, especially since the skill also handles API keys and billing-related operations.
The manifest description lists trigger phrases such as “国家贸易分解”, “进出口国家比较”, and “按国家统计贸易量” without clear boundaries, exclusions, or a narrow invocation context. These phrases are generic within trade-analysis conversations and may cause unintended activation because the file does not specify when this skill should not be used.
The document explicitly recommends sending request parameters, response data, and exception context to an error-reporting endpoint, and although it notes that sensitive fields are 'automatically desensitized,' it provides no concrete guarantees about what is redacted or when reporting is appropriate. In an agent/skill environment, these fields can easily contain user-provided business data, identifiers, or model context, so this creates a real privacy and data-minimization risk if operators forward full payloads by default.
The file can request a new API key and persist it locally, which is not directly justified by a read-only trade-list query skill. In this context, hidden credential provisioning and storage create unnecessary secret-handling risk and make it easier for a seemingly harmless query skill to establish durable authenticated access.
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:
The script writes the newly issued API key directly to a local .env file without an up-front warning, consent prompt, or hardening of file permissions. This can expose credentials through accidental inclusion in backups, source-control, shared home directories, or other local processes, and the risk is more concerning because the skill is not primarily an authentication tool.