T09 · Insecure Skill Coding Practices
- Location
scripts/auth.py:70- Finding
API Key File Is Created Without Explicitly Restrictive Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly an UpKuaJing email/API account tool, but it has overbroad marketing claims, weak API-key handling, and an undisclosed automatic version-check network call.
Install only if you are comfortable with a fee-incurring bulk-email tool using an UpKuaJing API key. Confirm recipients, content, and charges before sending; avoid passing --api_key on the command line; lock down ~/.upkuajing/.env permissions; and do not include secrets, email bodies, or recipient lists in error reports. Be aware that normal API use also performs an automatic vendor version check.
scripts/auth.py:70API Key File Is Created Without Explicitly Restrictive Permissions
scripts/mail_send.py:120API Keys Can Be Supplied Through Process Command-Line Arguments
scripts/version_check.py:92Automatic Version Check Sends Undisclosed Usage Metadata
The supplied code does not implement bulk email sending, delivery monitoring, open/click analytics, domain email discovery, lead generation, or campaign management. Its primary purpose is authentication and billing/account administration for an API service. It interacts with auth and payment-related endpoints (/agent/auth/create, /agent/auth/info, /agent/auth/pay/url) and writes API credentials locally, which is materially different from the declared cold-email marketing functionality. This is a clear description-behavior mismatch.
The supplied code chunk is a generic common utility module, not an email marketing or outreach implementation. It manages API authentication, request dispatch, logging, JSON/file I/O, and task metadata/result storage. There is no logic for composing emails, sending bulk messages, managing recipient lists, verifying business emails, or analyzing opens/clicks. While this module could support some larger system, this specific code does not substantiate the declared cold-email campaign and tracking functionality, so the description materially overstates and misrepresents the behavior shown.
The declared description focuses on outbound email marketing and analytics capabilities, but the actual code does none of that. Instead, it collects error-report parameters, auto-fills skill metadata, validates required fields, and sends an exception report to a platform error-reporting endpoint. This is a materially different primary purpose and introduces an undeclared capability—platform-side error reporting—that is unrelated to cold-email campaigns, email verification, or engagement tracking. Therefore, the description does not accurately represent the code's behavior.
The declared description presents a broader outbound sales-email platform: bulk cold-email campaigns, obtaining verified business-domain emails, and analyzing delivery/open/click performance. The supplied code chunk implements a much narrower capability: sending an email with subject/content to a list of addresses through an API. There is no logic for finding or verifying domain-based emails, no status polling or monitoring, and no analytics collection for opens or clicks. While bulk sending to multiple recipients is consistent with part of the description, the major advertised capabilities are absent, so the description does not accurately represent this code chunk.
The declared description presents a broad outbound email marketing tool that can run bulk campaigns, source verified business emails, and analyze engagement metrics such as opens and clicks. The supplied code does not implement those functions. It only calls '/agent/mail/task/list' to fetch existing email task records filtered by time and status. While listing mail tasks and their send status is loosely related to monitoring delivery workflows, it does not support the central claimed capabilities of campaign execution, email acquisition/verification, or open/click analytics. Therefore the description materially overstates and misrepresents what this code chunk actually does.
The code's primary purpose is narrow: query /agent/mail/task/record/list for details of an existing mail task and return recipient status records. This partially aligns with the 'monitor delivery status' portion of the description, since it supports status inspection and includes a read-status filter. However, the broader declared description claims major capabilities not present in the supplied code: running bulk campaigns, gaining verified domain emails, and analyzing open-and-click metrics. Because those are central declared functions and this code only lists task records for an already existing task, the description does not accurately represent the actual behavior of this code chunk.
The declared description promises a sales/marketing capability centered on bulk cold-email campaigns, verified corporate email discovery, and open/click analytics. The supplied code does none of that. Its sole purpose is operational maintenance for the skill itself: checking whether a newer version exists, caching the result, and notifying the user. This is a materially different primary purpose and involves undeclared behaviors such as local filesystem cache management and remote version API calls. Therefore, the description does not accurately represent the code chunk.
The skill instructs the agent to check for and use a credential stored in ~/.upkuajing/.env, which is a sensitive local secret. In the absence of narrowly declared permissions and explicit secret-handling boundaries, this creates a real risk of credential access beyond user expectations and could expose the API key through logs, prompts, or unintended downstream actions.
### **API Key Not Set**
First check if the `~/.upkuajing/.env` file has UPKUAJING_API_KEY;
If UPKUAJING_API_KEY is not set, prompt the user to choose:
1. User has one: User provides it (manually add to ~/.upkuajing/.env file)
2. User doesn't have one: Guide user to apply at [UpKuaJing Open Platform](https://developer.upkuajing.com/)
Wait for user selection;
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():
The script stores a newly issued API key in a plaintext .env file under the user's home directory. If file permissions are too broad, backups/sync tools capture the file, or other local processes can read it, the credential can be stolen and abused to access the associated API account.
"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")
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 skill declares executable behavior that reads environment variables, accesses local files, and calls remote APIs, but it does not define any explicit tool/permission scope. That creates an overbroad execution surface where a host agent may grant more capabilities than users expect, increasing the chance of unintended credential access, file access, or network actions.
The trigger phrases are broad enough to activate on generic marketing or lead-generation requests, which can cause the agent to invoke a fee-incurring and externally connected skill in contexts where the user did not clearly ask for it. In a cold-email tool, loose triggering is more dangerous because it can lead to unwanted outreach actions, privacy exposure, or unnecessary account charges.
The API documentation instructs agents to upload request parameters, response data, and exception context to a central error-reporting endpoint, which can easily include personal data, secrets, access tokens, email content, prospect lists, or other sensitive business information. Although the text says sensitive fields are 'automatically desensitized,' it does not define the coverage, guarantees, or require explicit minimization or user/operator warning, so this creates a real risk of oversharing confidential data during failure handling.
This code file contains natural-language strings that force a specific language/locale for the interface and operational guidance. Under the policy, locale constraints should either be optional for the user or clearly justified as region-specific; neither is stated here.
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 skill manifest describes bulk cold-email operations, delivery monitoring, verified business emails, and campaign analytics. This file adds a separate billing capability by creating recharge/payment orders, which is not part of sending campaigns or tracking email performance and therefore exceeds the described behavior.
The request/response logging functions write full API parameters and response bodies to local log files when enabled, with no redaction of sensitive fields. In this skill's context, requests and responses may contain email campaign data, recipient addresses, domain-based leads, and possibly authentication-related metadata, so enabling logging can create a local plaintext cache of sensitive business and personal data.
This script sends exception telemetry to a platform endpoint using request metadata and free-form context, but the skill’s stated purpose is bulk cold-email operations, not diagnostics or telemetry collection. That mismatch increases the risk of undisclosed data exfiltration of operational details, request identifiers, paths, or user-supplied error context that may contain sensitive information.
Detected: suspicious.exposed_secret_literal