T09 · Insecure Skill Coding Practices
- Location
scripts/auth.py:64- Finding
API Key Stored Without Enforced Restrictive File Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This paid colleague-lookup skill is mostly coherent, but it handles API keys and auxiliary platform calls in ways users should review before installing.
Before installing, confirm you are comfortable giving this skill a paid UpKuaJing API key and letting it contact UpKuaJing services. Do not allow the agent to print ~/.upkuajing/.env; use a redacted presence check instead, restrict the credential file permissions, and review every paid query, top-up order, and error report before it is sent.
scripts/auth.py:64API Key Stored Without Enforced Restrictive File Permissions
SKILL.md:39Documentation Directs the Agent to Print the Complete Credential File
requirements.txt:1Dependency Uses an Open-Ended Version Constraint Without Integrity Verification
The skill appears to perform remote version checks, read local metadata, and write cache data under the user's home directory, none of which is disclosed by its stated purpose. Undeclared update-checking and cache persistence create additional network and filesystem exposure that can leak usage patterns or introduce integrity concerns.
The skill appears to perform remote version checks, read local metadata, and write cache data under the user's home directory, none of which is disclosed by its stated purpose. Undeclared update-checking and cache persistence create additional network and filesystem exposure that can leak usage patterns or introduce integrity concerns.
The skill appears to perform remote version checks, read local metadata, and write cache data under the user's home directory, none of which is disclosed by its stated purpose. Undeclared update-checking and cache persistence create additional network and filesystem exposure that can leak usage patterns or introduce integrity concerns.
The skill appears to perform remote version checks, read local metadata, and write cache data under the user's home directory, none of which is disclosed by its stated purpose. Undeclared update-checking and cache persistence create additional network and filesystem exposure that can leak usage patterns or introduce integrity concerns.
The skill instructs reading a plaintext credential file from the user's home directory using a shell command. Exposing or encouraging direct inspection of secret-bearing .env files increases the chance of credential disclosure to logs, transcripts, or downstream tools.
This skill requires an API key. The API key is stored in the ~/.upkuajing/.env file:
cat ~/.upkuajing/.env
Example file content:
The skill workflow directs the agent to check for and potentially manage API keys in a local .env file, including prompting for user-supplied secrets and storing them on disk. This expands the skill from data lookup into credential collection and persistence, increasing risk of accidental disclosure or misuse.
### **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: You can apply using the interface (`auth.py --new_key`), the new key will be automatically saved to ~/.upkuajing/.env
Wait for user selection;
Automatically applying for a new API key and saving it to ~/.upkuajing/.env creates and persists credentials locally without clear security controls. In combination with the skill's external network behavior and broad contact-discovery purpose, this makes the context more dangerous because it normalizes silent credential provisioning for an unrelated business-intelligence task.
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: You can apply using the interface (`auth.py --new_key`), the new key will be automatically saved to ~/.upkuajing/.env
Wait for user selection;
### **Account Top-up**
The script's behavior is materially inconsistent with the declared skill purpose. Instead of finding internal colleagues or mapping stakeholders, it implements API key issuance, account lookup, pricing, and recharge flows for an external platform, which is a strong indicator of scope drift and can facilitate unauthorized monetization or hidden service enablement inside a seemingly unrelated 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():
The script writes a newly issued API key to a .env file without any visible permission hardening or secure secret-store usage. Storing credentials in plaintext on disk can expose them to other local users, backup systems, or accidental inclusion in logs, archives, or repositories.
"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 exact environment variable name and secret-storage path in error messages increases sensitive operational disclosure and encourages manual secret handling. In combination with plaintext local storage, this makes accidental leakage or mishandling of credentials more likely.
except IOError as e:
return {
"success": False,
"message": f"API密钥申请成功,但保存到 .env 文件失败:{str(e)}。\n请手动设置环境变量 {API_KEY_ENV}。",
"envFilePath": str(env_file)
}
Recharge-order creation and pricing retrieval are unrelated to the stated colleague-discovery function and introduce financial operations into a deceptive context. Hidden billing capabilities increase the risk of user confusion, unintended charges, and abuse of enterprise environments where agents are expected to perform only contact-discovery tasks.
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 finding internal company teammates and mapping decision-making circles, but this file implements exception reporting to a platform endpoint and auto-populates skill metadata. Reporting runtime errors is not part of the user-facing teammate/contact discovery behavior claimed by the skill description.
The skill declares executable behaviors that imply environment access, file reads/writes, and network communication, but it does not define an explicit tool scope or permissions boundary. That omission increases the chance of over-privileged execution and makes it harder for reviewers or runtime policy engines to constrain what the skill can do.
The trigger phrases are broad enough to match common sales, networking, and business-research requests, which can cause the skill to activate outside a narrowly intended context. Over-broad invocation raises the risk of unintended data collection, contact discovery, or execution of fee-incurring queries when users did not specifically request this capability.
The skill explicitly promotes uncovering hidden stakeholders and mapping client-side decision-making circles, which can facilitate profiling and non-transparent contact network expansion. In this business-intelligence context, the language makes the capability more sensitive because it encourages discovery of people who may not expect to be surfaced for outreach or influence mapping.
The documentation explicitly encourages sending exception context plus raw request parameters and response data to a centralized error-report API, while only stating that sensitive fields are 'automatically desensitized' without defining scope, guarantees, or user/operator safeguards. In a skill that maps internal colleagues and stakeholder networks, those payloads can plausibly contain internal identifiers, relationship data, and other sensitive enterprise information, so error reporting can become an unintended data-exfiltration channel if logging is overbroad or masking is incomplete.
The module docstring and all user-facing CLI descriptions/messages are written only in Chinese, which imposes a specific language on users. The file does not indicate that Chinese is optional, user-selected, or required for a documented region-specific purpose.
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:
Detected: suspicious.exposed_secret_literal