T09 · Insecure Skill Coding Practices
- Location
SKILL.md:39- Finding
API Key May Be Exposed Through Terminal or Agent Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its paid LinkedIn alumni lookup purpose, but it needs review because it can expose and persist API credentials insecurely and performs extra platform housekeeping calls.
Install only if you are comfortable using a paid Upkuajing API credential. Do not let the agent print `~/.upkuajing/.env`; use a presence-only check or environment variable instead. Confirm every billable query or recharge action yourself, avoid including sensitive request or response data in error reports, and consider tightening permissions on `~/.upkuajing/.env` if this skill creates it.
SKILL.md:39API Key May Be Exposed Through Terminal or Agent Output
scripts/auth.py:62API Key File Is Created Without Explicit Restrictive Permissions
requirements.txt:1Dependency Is Not Reproducibly Pinned or Integrity-Verified
Remote version checks, local cache writes, and parsing local metadata are extra behaviors not reflected in the high-level alumni-query purpose. While common operationally, undisclosed update-check logic creates additional outbound communication and local state changes that can expose metadata or be abused if the update channel is compromised.
Remote version checks, local cache writes, and parsing local metadata are extra behaviors not reflected in the high-level alumni-query purpose. While common operationally, undisclosed update-check logic creates additional outbound communication and local state changes that can expose metadata or be abused if the update channel is compromised.
Remote version checks, local cache writes, and parsing local metadata are extra behaviors not reflected in the high-level alumni-query purpose. While common operationally, undisclosed update-check logic creates additional outbound communication and local state changes that can expose metadata or be abused if the update channel is compromised.
Remote version checks, local cache writes, and parsing local metadata are extra behaviors not reflected in the high-level alumni-query purpose. While common operationally, undisclosed update-check logic creates additional outbound communication and local state changes that can expose metadata or be abused if the update channel is compromised.
Remote version checks, local cache writes, and parsing local metadata are extra behaviors not reflected in the high-level alumni-query purpose. While common operationally, undisclosed update-check logic creates additional outbound communication and local state changes that can expose metadata or be abused if the update channel is compromised.
The skill explicitly instructs reading and potentially revealing the contents of the local API key file using a shell command. This is direct secret exposure: if the agent follows the instruction, credentials stored on the host can be disclosed to the user or leaked into chat history, logs, or downstream systems.
Referencing and reading the .env file that stores UPKUAJING_API_KEY creates a credential-access path. In this skill context, the danger is elevated because the instructions encourage direct shell inspection of the file, which can expose reusable API credentials beyond the minimum needed to perform the alumni lookup.
使用此技能需要API密钥。API密钥保存在 ~/.upkuajing/.env 文件中:
cat ~/.upkuajing/.env
文件内容示例:
The instruction to check ~/.upkuajing/.env for the API key and optionally trigger automatic key application/saving couples credential discovery with local secret persistence. That increases the chance of unauthorized access, accidental disclosure, or later misuse of a newly created token stored on disk.
### **未设置API密钥**
请先检查 `~/.upkuajing/.env` 文件是否有 UPKUAJING_API_KEY;
如果未设置 UPKUAJING_API_KEY API密钥,请提示并让用户选择:
1. 用户有,由用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有,你可使用接口进行申请(`auth.py --new_key`),申请到新密钥后,会自动保存到 ~/.upkuajing/.env
等待用户选择;
Automatically saving newly obtained API keys into a local .env file creates persistent credential material on the filesystem. In an agent environment with file access, that persistence broadens the blast radius: other tools, sessions, or logs may access the token later, and the user may be unaware that a sensitive secret was written locally.
请先检查 `~/.upkuajing/.env` 文件是否有 UPKUAJING_API_KEY;
如果未设置 UPKUAJING_API_KEY API密钥,请提示并让用户选择:
1. 用户有,由用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有,你可使用接口进行申请(`auth.py --new_key`),申请到新密钥后,会自动保存到 ~/.upkuajing/.env
等待用户选择;
### **账户充值**
The file implements API key issuance, account lookup, pricing, and recharge flows that are materially unrelated to the stated LinkedIn alumni/former-employee discovery purpose. This capability mismatch is dangerous because it introduces billing and credential-management functionality into a data-enrichment skill, increasing the chance of unauthorized account manipulation or hidden monetization behavior.
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 writes the newly issued API key directly to a plaintext .env file under the user's home directory. Plaintext secret storage can lead to credential disclosure through weak file permissions, backups, logs, or other local processes, enabling unauthorized API use and possible account/billing abuse.
"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")
清晰的模块文档将该文件定义为“跨境魔方API脚本公共工具”,并把 API_BASE_URL 指向 openapi.upkuajing.com。技能清单描述的是基于 LinkedIn 的人员、企业、校友和离职员工关联挖掘,但该公共模块实际实现的是连接另一套跨境/外部平台 API 的通用请求能力,表现出明显的用途错位。
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 LinkedIn-derived alumni and former-employee relationship data to identify business opportunities. This file instead implements telemetry/error reporting to a platform endpoint, which is operational infrastructure behavior unrelated to the stated business function of alumni discovery.
The skill declares broad capabilities in practice (environment access, local file read/write, and network use) but does not explicitly scope or constrain those powers. This weakens reviewability and increases the chance that a host agent invokes sensitive operations beyond the user-visible alumni-query purpose.
The file’s natural-language content, including the description and all operating instructions, is exclusively in Chinese. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified, which is not present here.
该文档明确说明异常上报会向远程 API 发送 requestParams、responseData 和 context,但没有显式提醒这些字段可能包含业务数据、错误堆栈或其他敏感信息,也未要求调用方在上报前做最小化与人工审查。对于会处理人员、企业和 LinkedIn 相关数据的技能来说,这会增加敏感请求内容被过度收集并外发到平台侧的风险。
The module docstring and all user-facing help/messages are written only in Chinese, which imposes a language choice on users without any opt-in or alternative locale path. The policy explicitly calls out language or locale constraints as violations when they are forced rather than optional or justified.
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