T09 · Insecure Skill Coding Practices
- Location
scripts/auth.py:62- Finding
API Key Disclosure Through Credential-File Output and Insecure File Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches a paid LinkedIn company-search tool, but it handles API keys, payment-order flows, local result storage, and an undisclosed version-check cache in ways users should review before installing.
Review this skill before installing. Use it only if you are comfortable sending search queries to Upkuajing, paying for API calls, and storing results locally. Do not print the `.env` file in chat or logs; prefer an environment variable or secret store, restrict permissions on `~/.upkuajing` and task data, and manually confirm any recharge, paid query, or error report that may include request or response details.
scripts/auth.py:62API Key Disclosure Through Credential-File Output and Insecure File Permissions
scripts/common.py:423Sensitive Search Results and Query Metadata Use Process-Default File Permissions
requirements.txt:1Unbounded Dependency Version Allows Unreviewed Future Releases
The finding indicates undeclared version-check networking, reads of SKILL.md, and writes to a cache file under the user's home directory even when no core LinkedIn search is performed. Hidden background behaviors are risky because they create side effects and external communications unrelated to the user-requested business function, undermining transparency and increasing the attack surface.
The finding indicates undeclared version-check networking, reads of SKILL.md, and writes to a cache file under the user's home directory even when no core LinkedIn search is performed. Hidden background behaviors are risky because they create side effects and external communications unrelated to the user-requested business function, undermining transparency and increasing the attack surface.
The finding indicates undeclared version-check networking, reads of SKILL.md, and writes to a cache file under the user's home directory even when no core LinkedIn search is performed. Hidden background behaviors are risky because they create side effects and external communications unrelated to the user-requested business function, undermining transparency and increasing the attack surface.
The skill explicitly instructs reading ~/.upkuajing/.env with cat, exposing a local credential store to the agent workflow. Even if intended to check setup, encouraging direct file reads of secret-bearing files increases the chance of accidental secret disclosure to the model, logs, or downstream outputs.
使用此技能需要API密钥。API密钥保存在 ~/.upkuajing/.env 文件中:
cat ~/.upkuajing/.env
文件内容示例:
The setup flow instructs checking the user's .env file and, if absent, obtaining a new key and automatically saving it under the user's home directory. This blends credential discovery, acquisition, and persistence into a search skill, increasing the risk of unauthorized secret handling and long-lived credential storage without strong scope controls.
### **未设置API密钥**
请先检查 `~/.upkuajing/.env` 文件是否有 UPKUAJING_API_KEY;
如果未设置 UPKUAJING_API_KEY API密钥,请提示并让用户选择:
1. 用户有,由用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有,你可使用接口进行申请(`auth.py --new_key`),申请到新密钥后,会自动保存到 ~/.upkuajing/.env
等待用户选择;
This repeated instruction reinforces that the agent may inspect and modify ~/.upkuajing/.env, a sensitive local credential file. In the context of a data-search skill, that is more dangerous because the user expectation is low-risk querying, not secret file access and persistence on disk.
请先检查 `~/.upkuajing/.env` 文件是否有 UPKUAJING_API_KEY;
如果未设置 UPKUAJING_API_KEY API密钥,请提示并让用户选择:
1. 用户有,由用户提供(手动添加到 ~/.upkuajing/.env 文件)
2. 用户没有,你可使用接口进行申请(`auth.py --new_key`),申请到新密钥后,会自动保存到 ~/.upkuajing/.env
等待用户选择;
### **账户充值**
The file implements API key provisioning, account information lookup, and payment-related operations that are materially broader than the declared LinkedIn company search skill purpose. In an agent-skill ecosystem, this kind of scope expansion increases trust abuse risk because users may invoke a search skill without expecting credential enrollment or billing workflows.
The function is explicitly designed to handle API secrets via a .env file, indicating local credential material is being managed in plaintext file-based storage. Plaintext secret handling raises the risk of accidental disclosure through backups, permissive file permissions, or local compromise, especially in an agent environment where users may not expect credential persistence.
"""
申请新的 API 密钥。
"""
# 检查是否已存在 .env 文件和 API key
env_file = UPKUAJING_ENV_FILE
if env_file.exists():
Reading an existing .env file to recover API keys confirms the skill accesses locally persisted secrets. This expands the credential exposure surface because any process with access to the file may obtain the key, and the skill normalizes secret retrieval from a non-hardened location.
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 the newly issued API key directly to a .env file stores a live credential in plaintext on disk. If that file is readable by other local users, synced to cloud storage, committed to source control, or included in logs/backups, the credential can be stolen and used to access the backend API.
"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 continues to encourage manual environment-variable handling and discloses the secret storage path, reinforcing insecure credential management patterns. While lower severity than the actual write, it still contributes to unsafe operational handling of secrets.
except IOError as e:
return {
"success": False,
"message": f"API密钥申请成功,但保存到 .env 文件失败:{str(e)}。\n请手动设置环境变量 {API_KEY_ENV}。",
"envFilePath": str(env_file)
}
Creating recharge orders and returning payment URLs is a financial capability unrelated to company search/filtering, so embedding it here creates an unexpected billing surface. If exposed through the skill, it could be abused for unauthorized charge initiation, phishing-like payment redirection, or stealth monetization under a misleading capability label.
The skill metadata claims a LinkedIn company search capability, but this module is wired to a different third-party service and its authentication flow. That mismatch is dangerous because it can cause users and reviewers to grant trust and credentials under false assumptions, enabling undisclosed data transfer to an external provider.
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'
# 日志开关
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_env_file() -> Dict[str, str]:
"""
从 ~/.upkuajing/.env 文件加载环境变量。
Returns:
环境变量字典
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_env_file() -> Dict[str, str]:
"""
从 ~/.upkuajing/.env 文件加载环境变量。
Returns:
环境变量字典
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_env_file() -> Dict[str, str]:
"""
从 ~/.upkuajing/.env 文件加载环境变量。
Returns:
环境变量字典
The skill declares capabilities that include environment access, local file read/write, and network activity, but does not scope or constrain those tools in the manifest. This creates unnecessary trust ambiguity: a user invoking a company-search skill would not reasonably expect credential file access, local persistence, or auxiliary network operations such as pricing, recharge, version checks, and telemetry-related calls.
The documentation expands the skill from company search into API key application, recharge, pricing, and exception reporting workflows. While not proof of exploit code by itself, this is a substantive scope creep indicator that can lead users to authorize credential, billing, and outbound-reporting actions under the guise of a simple search skill.
该 markdown 明确写明“行业和产品名称需使用英文”,属于自然语言层面的语言约束。文档未说明这是用户可选项,也未将其限定为特定地区合规要求,因此构成语言/locale policy 风险。
该处再次以强制语气规定“行业名称需要使用英文”。这会将特定语言作为默认要求施加给用户,而没有提供可选语言方案或明确说明该限制的必要性。
The API explicitly supports filtering for the existence of personal and business contact channels, including valid phone/email and core member contact availability, but the documentation provides no privacy, consent, or lawful-use constraints. In a lead-generation and ABM context, this materially increases the risk of bulk targeting, scraping, and misuse of personal contact data for unsolicited outreach or profiling.
The response schema states that a record may include displayed employee contact information, exposing sensitive personal data without any warning, masking guidance, or access-control expectations in the documentation. Because the skill is designed for customer development and account-based marketing, the surrounding context makes this more dangerous by encouraging operational use of exposed contact details for direct outreach at scale.
The documentation explicitly allows transmitting request parameters, response data, and exception context to an error-reporting API, which can include sensitive business data, identifiers, stack traces, or user-provided content. Although it mentions automatic masking of sensitive fields, it does not define what is redacted, require minimization, or warn operators not to include secrets and personal data, creating a realistic privacy and data-exposure risk through logging/telemetry.
The module docstring and user-facing CLI descriptions are written only in Chinese, which imposes a specific language on users. Under the policy, language constraints should either be optional for the user or clearly justified as region-specific.
Detected: suspicious.exposed_secret_literal