T09 · Insecure Skill Coding Practices
- Location
scripts/auth.py:63- Finding
API Key Stored and Displayed Without Adequate Local Protection
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly performs the advertised paid customs-port lookup, but it also handles API keys and account/payment support in ways users should review carefully before installing.
Review this before installing if the API account has funds or sensitive trade data access. Use a dedicated low-balance API key if possible, avoid printing ~/.upkuajing/.env, check local file permissions, and only approve paid queries, recharge URL creation, or error reports when you intend them.
scripts/auth.py:63API Key Stored and Displayed Without Adequate Local Protection
requirements.txt:1Unbounded Third-Party Dependency Installation
The skill reportedly performs version checks, reads local metadata, writes cache files under ~/.upkuajing, and emits upgrade notices—behaviors unrelated to querying port-trade data. These side behaviors increase hidden network and filesystem activity and make the skill more dangerous than its declared business function suggests.
The skill reportedly performs version checks, reads local metadata, writes cache files under ~/.upkuajing, and emits upgrade notices—behaviors unrelated to querying port-trade data. These side behaviors increase hidden network and filesystem activity and make the skill more dangerous than its declared business function suggests.
The skill reportedly performs version checks, reads local metadata, writes cache files under ~/.upkuajing, and emits upgrade notices—behaviors unrelated to querying port-trade data. These side behaviors increase hidden network and filesystem activity and make the skill more dangerous than its declared business function suggests.
The skill instructs reading ~/.upkuajing/.env directly, including a literal cat command, to access the API key. Encouraging direct file reads of a secret-bearing env file creates clear credential exposure risk: the key could be printed, logged, echoed back to users, or mishandled by the agent beyond the minimum needed for authentication.
本技能需要API密钥。API密钥存储在 ~/.upkuajing/.env 文件中:
cat ~/.upkuajing/.env
文件内容示例:
The workflow explicitly tells the agent to inspect the local .env file for UPKUAJING_API_KEY and supports writing user-provided secrets into that file. This combines credential discovery and local secret storage in a general-purpose skill, which increases the chance of secret leakage, persistence beyond user intent, and compromise of other tools that trust that file.
### **API密钥未设置**
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
At this line the skill combines verification of a local secret file with instructions for manual insertion or automatic persistence of a newly issued API key. In the context of a skill supposedly meant for trade-port queries, this is especially dangerous because it normalizes credential access and storage operations that are unrelated to the narrow business query and could be abused to harvest or persist secrets.
首先检查 `~/.upkuajing/.env` 文件中是否有 UPKUAJING_API_KEY;
如果未设置,请让用户选择:
1. 用户已有密钥:用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有密钥:通过界面申请(`auth.py --new_key`),新密钥会自动保存到 ~/.upkuajing/.env
等待用户选择;
### **账户充值**
The file implements account management, API key issuance, and recharge/payment workflows that are outside the declared purpose of a port-trade lookup skill. This kind of scope mismatch is dangerous because users or host agents may grant trust based on the advertised data-query function, while the code quietly enables credential provisioning and billing-related actions.
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():
Reading an existing .env file to inspect API keys means the skill handles secrets directly from local plaintext storage. In the context of an unrelated analytics skill, direct secret access increases the blast radius of compromise and may expose credentials through logs, errors, or unintended code paths.
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 a newly issued API key into a local .env file stores a live credential in plaintext on disk. This is dangerous because local files are commonly leaked through backups, misconfigured permissions, debugging, or accidental check-in, and the skill context does not justify embedded credential persistence for a simple trade-query function.
"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")
Returning the environment file path in error handling increases disclosure about where credentials are expected to be stored, which can aid post-compromise secret targeting. While not severe by itself, combined with plaintext .env storage it contributes to easier discovery and harvesting of sensitive material.
except IOError as e:
return {
"success": False,
"message": f"API密钥申请成功,但保存到 .env 文件失败:{str(e)}。\n请手动设置环境变量 {API_KEY_ENV}。",
"envFilePath": str(env_file)
}
The presence of recharge-order creation in a logistics-analysis skill introduces unnecessary financial capability. Even if intended for legitimate account funding, embedding payment-related actions in an unrelated skill expands attack surface and increases the risk of unauthorized charges or social engineering through a trusted analytical interface.
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 company customs trade port list data for logistics analysis, but this file implements a separate capability: reporting runtime exceptions to a platform endpoint. That telemetry/error-reporting behavior is not part of querying or analyzing port trade data and represents functionality outside the manifest's stated scope.
The skill declares capabilities that imply environment access, filesystem interaction, and network use, but it does not explicitly scope or constrain those powers with an allowlist. That creates an over-privileged execution model where a seemingly simple data-query skill can also access local secrets or perform unrelated remote actions, increasing the blast radius if the skill is misused or compromised.
The listed triggers include short noun phrases such as “海关港口列表” and “公司贸易港口详情,” but the file does not define when these phrases should activate this skill versus related customs/company analysis skills. There are no negative examples or scope constraints, which increases the chance of unintended invocation for adjacent logistics or trade-analysis requests.
The document explicitly allows sending request parameters, response payloads, and free-form error context to an error-reporting endpoint. Even though it states that sensitive fields are 'automatically desensitized,' it does not define coverage, guarantees, or a requirement to minimize data before submission, so secrets, personal data, trade data, or stack traces could still be exposed to the platform. In a customs/logistics skill, those fields may contain commercially sensitive import/export information, making the reporting path a meaningful data-leak channel.
The module documentation advertises API-key application and recharge features that conflict with the externally stated port-query purpose. This discrepancy is a security concern because misleading capability descriptions make it harder for reviewers and users to understand the true privilege and financial scope of the skill.
The code can request a new API key and persist it locally, which is unrelated to simple port-list querying and creates credential-handling risk. In this context, hidden credential lifecycle management is dangerous because it normalizes secret generation/storage in a skill users may only expect to perform read-only trade analysis.
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:
This code file contains natural-language documentation and console messages exclusively in Chinese, beginning with the module docstring and continuing throughout user-facing output. Under the policy, forcing a specific language without offering the user a language/locale choice can be a natural-language policy violation.
Detected: suspicious.exposed_secret_literal