T09 · Insecure Skill Coding Practices
- Location
scripts/auth.py:63- Finding
API key is stored without explicitly restrictive filesystem permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill performs the advertised trade-summary query, but its API-key handling, recharge/payment-order flow, and automatic update/reporting helpers create sensitive account and credential risk that users should review before installing.
Review this before installing if you will use a paid Upkuajing account. Do not print or paste the full API key into chat, logs, screenshots, or support tickets; prefer an environment variable or a securely permissioned credential file. Treat recharge order creation, account-info lookup, pricing lookup, exception reporting, and every billable query as actions that need explicit confirmation, and minimize any request or response data sent in error reports.
scripts/auth.py:63API key is stored without explicitly restrictive filesystem permissions
SKILL.md:39Setup instructions disclose the complete credential through terminal output
requirements.txt:1Dependency installation is not reproducible because httpx has no upper or exact version bound
The documented purpose is limited to trade overview queries, but the finding indicates additional version-check logic involving local file writes, metadata parsing, and remote update checks. Even if benign, these undeclared behaviors widen the attack surface and create unexpected outbound communication and local state changes not implied by the skill’s stated purpose.
The documented purpose is limited to trade overview queries, but the finding indicates additional version-check logic involving local file writes, metadata parsing, and remote update checks. Even if benign, these undeclared behaviors widen the attack surface and create unexpected outbound communication and local state changes not implied by the skill’s stated purpose.
The documented purpose is limited to trade overview queries, but the finding indicates additional version-check logic involving local file writes, metadata parsing, and remote update checks. Even if benign, these undeclared behaviors widen the attack surface and create unexpected outbound communication and local state changes not implied by the skill’s stated purpose.
The skill instructs reading a plaintext credential file from the user’s home directory using a shell command. Accessing and potentially exposing secrets from ~/.upkuajing/.env is sensitive credential handling and can leak API keys through logs, chat output, or unintended tool execution.
本技能需要API密钥。API密钥存储在 ~/.upkuajing/.env 文件中:
cat ~/.upkuajing/.env
文件内容示例:
The skill directs the agent to inspect for an API key and, if absent, to have the user provide one for manual placement into a local .env file or generate one that is auto-saved there. This normalizes insecure secret collection and persistence, increasing the risk of credential leakage, theft, and reuse across sessions or other tools on the host.
### **API密钥未设置**
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
This line continues the insecure credential-management workflow by directing checks of a local secret file and persistence of newly issued keys into that file. In the context of a skill marketed as a trade-query tool, this is more dangerous because users may not expect secret-file access or credential storage side effects from a seemingly simple data lookup capability.
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
### **账户充值**
This file implements account management, API key issuance, billing/recharge, and pricing operations that are unrelated to a skill advertised as providing country-level trade overview summaries. Such hidden or extraneous capabilities expand the attack surface and create an unexpected trust boundary, especially because they can modify account state and provision credentials.
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 plaintext .env file creates a credential exposure risk if file permissions are weak, the home directory is shared, backups are accessible, or other local processes can read the file. In the context of a skill that does not need to manage credentials, this makes the behavior more concerning because it silently persists sensitive secrets outside the expected skill scope.
"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 ability to create recharge/payment orders is a financial side-effect that is not justified by a trade-summary skill. If invoked unexpectedly, it could trigger unauthorized billing flows, confuse users, or be abused to redirect users into payment actions under false pretenses.
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 read-oriented trade overview summary skill that returns annual/quarterly trade totals and supplier/buyer counts. In contrast, this code gathers execution-context fields and sends them to an '/agent/skill/error/report' API, which is operational telemetry/reporting behavior rather than trade-summary retrieval.
The skill declares no explicit tool scope or permission boundaries while its documented behavior includes environment access, local file reads/writes, and network/API operations. That combination creates an over-privileged skill surface where a caller may invoke sensitive capabilities that are not transparently constrained or auditable.
文件名和描述中的“zh”以及全文仅以中文提供操作说明,体现出该技能面向固定语言环境,但文档中没有说明这是用户可选项,也没有提供语言切换或显式 opt-in。按照语言/地区策略,强制特定语言而无选择机制属于自然语言策略风险。
该描述在 Trigger 中列出“贸易概览汇总”“年度贸易统计”“国家贸易总量”“贸易量概览”等短语,其中部分表达较泛,且没有说明触发上下文、适用范围或负面示例。对于 markdown/manifest 类文件,这种缺少约束的触发说明可能与一般贸易分析请求重叠,增加非预期调用风险。
The document instructs agents to report exceptions to a remote API and explicitly allows inclusion of request parameters, response data, and error context, which can contain sensitive operational or user data. Although it notes that sensitive fields are 'automatically desensitized,' it does not define guarantees, scope, or required minimization, so users may over-share confidential data off-box without understanding the privacy implications.
The module docstring and all user-facing CLI descriptions/messages are written only in Chinese, which constitutes a language-specific user experience with no opt-in or alternative locale. The stated policy requires flagging language or locale constraints when the skill forces a specific language without user choice.
This code provisions new API keys and stores them locally, which is outside the declared trade-summary functionality. Credential issuance inside an unrelated skill increases the risk of unauthorized account setup, credential sprawl, and misuse if the local environment or surrounding tooling is compromised.
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: