T09 · Insecure Skill Coding Practices
- Location
SKILL.md:39- Finding
Credential Disclosure Through Secret-File Printing Instructions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its customs-data purpose, but it should be reviewed because it can expose or persist API keys unsafely and performs an undisclosed version-check with local caching.
Review this skill before installing. Do not let an agent print or paste the contents of ~/.upkuajing/.env; use an environment variable or protected secret store where possible, restrict the key file to owner-only access, and be aware that the skill can create API keys, query account/balance information, create recharge payment URLs, report errors to the vendor, and run a background version check when API requests are made.
SKILL.md:39Credential Disclosure Through Secret-File Printing Instructions
scripts/auth.py:62API Key File Is Created Without Explicit Restrictive Permissions
requirements.txt:1Unbounded Third-Party Dependency Version
The skill appears to perform version checking, local cache writes, and outbound requests for upgrade detection, none of which are disclosed by the stated purpose of returning customs product data. These hidden side behaviors are dangerous because they introduce extra network and filesystem actions that can leak metadata, persist state, or create an unexpected attack surface beyond the core user task.
The skill appears to perform version checking, local cache writes, and outbound requests for upgrade detection, none of which are disclosed by the stated purpose of returning customs product data. These hidden side behaviors are dangerous because they introduce extra network and filesystem actions that can leak metadata, persist state, or create an unexpected attack surface beyond the core user task.
The skill appears to perform version checking, local cache writes, and outbound requests for upgrade detection, none of which are disclosed by the stated purpose of returning customs product data. These hidden side behaviors are dangerous because they introduce extra network and filesystem actions that can leak metadata, persist state, or create an unexpected attack surface beyond the core user task.
The skill instructs reading ~/.upkuajing/.env directly, including an example using cat, which exposes secret material in plaintext. In an agent environment, encouraging direct file reads of a credential store increases the risk of secret disclosure to logs, transcripts, the model context, or an unintended user-visible response.
本技能需要API密钥。API密钥存储在 ~/.upkuajing/.env 文件中:
cat ~/.upkuajing/.env
文件内容示例:
The skill directs users or the runtime to manage API keys by writing them into ~/.upkuajing/.env, coupling credential handling with a general-purpose skill flow. This is dangerous because local file-based secret storage invites accidental exposure, weakens separation of duties, and can cause secrets to be persisted in places accessible to other tools or sessions.
### **API密钥未设置**
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
Automatically saving a newly issued API key to ~/.upkuajing/.env expands the skill from data retrieval into credential acquisition and persistence. This is risky because secret creation and storage are sensitive operations that can be abused or mishandled, especially when performed by a skill that is expected to only query product-trade data.
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
### **账户充值**
The file implements authentication, account lookup, pricing, and recharge-order creation, which are materially outside the stated skill purpose of querying customs product-list data. This scope expansion increases attack surface and can enable unexpected financial or account-management actions through a skill that users would not reasonably expect to have those capabilities.
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():
The script writes a newly issued API key directly into a .env file, creating plaintext local secret storage. If the home directory, backups, logs, container layers, or repo workspace are accessible to other users/processes, the key can be recovered and abused for unauthorized API use and possible billing impact.
"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 error path encourages manual environment-variable handling after a failed write, which is not a vulnerability by itself, but it reinforces insecure secret-handling patterns around plaintext/local environment configuration. In practice this can lead to accidental disclosure through shell history, process listings in some environments, or misconfigured deployment files.
except IOError as e:
return {
"success": False,
"message": f"API密钥申请成功,但保存到 .env 文件失败:{str(e)}。\n请手动设置环境变量 {API_KEY_ENV}。",
"envFilePath": str(env_file)
}
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 file implements a generic platform error-reporting capability rather than the declared customs product-list querying function. This expands the skill's behavior beyond its manifest and can enable unauthorized transmission of request metadata and context to a backend endpoint, which is especially risky in agent environments where hidden utility functions may exfiltrate operational data. The mismatch between manifest and implementation increases suspicion because users and reviewers would not expect this side-effect from a customs product-list skill.
The skill declares capabilities that imply environment access, local file read/write, and network use, but it does not define an explicit tool scope or permission boundary. This is dangerous because the runtime may grant broader access than the user expects, making it easier for the skill to read secrets, modify local state, or contact unrelated endpoints without clear authorization.
L003 的 Trigger 列表中包含“分页产品查询”“公司产品贸易详情”“贸易产品下钻”等表述,这些短语缺少对海关贸易数据、公司主体或特定系统上下文的限定,容易与一般数据查询类请求重叠。文件中也未提供负面示例或排除条件来说明哪些相似表述不应激活该技能。
The document explicitly instructs callers to transmit request parameters, response payloads, and exception context to an error-reporting endpoint, while only stating that sensitive fields will be 'automatically desensitized' and giving no explicit user-facing warning, minimization guidance, or consent boundary. In a trade-data skill context, these fields can contain company identifiers, query contents, internal stack traces, and other potentially sensitive operational data, creating a real privacy and data-leakage risk if over-collected or improperly scrubbed.
The top-level docstring and all user-facing descriptions are written only in Chinese, which constitutes a language/locale constraint in the skill's natural-language interface. The file does not indicate that Chinese is optional, user-selected, or required for a documented region-specific reason.
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 file's natural-language descriptions and user-facing messages are consistently hard-coded in Chinese, with no indication that the user can choose another language or locale. The policy requires flagging language/locale constraints when they are imposed without opt-in or documented justification.
The code can log full request parameters and full API responses to local files, which may include sensitive business data, search inputs, and potentially account-related metadata. Although logging is currently disabled by default, the capability is built in and writes unredacted content to persistent storage without any sanitization, minimization, or manifest disclosure.
Manifest 将技能描述为海关产品列表查询与分析,但该公共模块除发起查询外,还创建任务目录并将元数据和结果持续写入本地文件。对查询型技能而言,网络请求是预期实现细节,但持久化任务状态和结果属于额外行为,超出了描述中体现的只读查询范围。