T09 · Insecure Skill Coding Practices
- Location
scripts/tools.py:15- Finding
Potentially Sensitive User Context Is Transmitted to an External Service Without Explicit Disclosure
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This remote prompt/template skill is mostly purpose-aligned, but it stores an API key in a local plaintext .env file and can send that key and user context to a configurable endpoint.
Review before installing. Use this only if you are comfortable sending prompt inputs, project context, and bug details to the XiaoBenYang MCP API. Do not provide secrets or private source code as context. Prefer setting the API key through a secure environment/secret mechanism, verify .env is not committed or shared, and avoid using untrusted .env files that could change the API endpoint.
scripts/tools.py:15Potentially Sensitive User Context Is Transmitted to an External Service Without Explicit Disclosure
scripts/config.py:42API Key Is Persisted in a Plaintext Working-Directory File Without Restrictive Permissions
scripts/config.py:11Environment-Controlled Base URL Can Redirect Credentials and User Content to an Attacker-Controlled Host
requirements.txt:1Dependencies Are Specified With Open-Ended Minimum Versions
The skill claims to generate prompts/templates, but it also instructs reading/writing a local .env file, modifying environment variables, and persisting an API key, with references inconsistent with the stated product domain. Hidden credential storage and configuration mutation materially expand the trust and security implications beyond the declared purpose.
The skill claims to generate prompts/templates, but it also instructs reading/writing a local .env file, modifying environment variables, and persisting an API key, with references inconsistent with the stated product domain. Hidden credential storage and configuration mutation materially expand the trust and security implications beyond the declared purpose.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
model_config = SettingsConfigDict(
env_prefix="XBY_GAOKAO_",
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
The code manually reads .env and extracts XBY_APIKEY outside the settings framework, creating a direct secret-access path that bypasses normal validation and central secret-handling controls. In the context of a prompt-generation skill, custom credential scraping is more dangerous because it broadens secret exposure logic beyond what is necessary and increases the chance of mishandling or future extension into broader file harvesting.
default_year: int = 2025
def model_post_init(self, __context):
# 强制从 .env 文件读取 XBY_APIKEY
env_path = Path(".env")
if env_path.exists():
content = env_path.read_text(encoding="utf-8")
The explicit existence check and subsequent read of .env is part of custom secret extraction logic. While not malicious on its face, it unnecessarily expands credential access behavior and increases exposure risk if the file contains other sensitive entries or if future edits broaden parsing.
def model_post_init(self, __context):
# 强制从 .env 文件读取 XBY_APIKEY
env_path = Path(".env")
if env_path.exists():
content = env_path.read_text(encoding="utf-8")
for line in content.splitlines():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
if line.startswith("XBY_APIKEY="):
self.api_key = line.split("=", 1)[1].strip()
break
# 如果环境变量有值,覆盖 .env 的值
env_val = os.getenv("XBY_APIKEY", "")
if env_val:
self.api_key = env_val
This function is specifically designed to persist an API key into a local .env file, creating a plaintext credential store on disk. If the machine, workspace, repository, logs, backups, or container image are accessed by another party, the credential can be recovered and abused, making this the strongest secret-handling issue in the file.
def save_api_key_to_env(api_key: str) -> bool:
"""将API key保存到.env文件"""
try:
env_path = Path(".env")
lines = []
if env_path.exists():
lines = env_path.read_text(encoding="utf-8").splitlines()
The skill declares no explicit tool scope or permission boundaries while its documented/project capabilities include environment access, file reads/writes, and network calls. In an agent setting, missing least-privilege constraints increases the blast radius if the skill is misused, prompt-injected, or invoked unexpectedly.
The manifest presents a dynamic prompt/template generator, but the actual documented flow includes collecting an external API key, storing it, and returning raw third-party API data. This discrepancy can cause users to expose credentials or approve data-sharing behavior they did not reasonably expect from the stated skill purpose.
The skill instructs the model to ask the user for an API key and store it, but provides no warning about persistence, exposure risk, revocation, or safer alternatives. Collecting secrets in plain-language conversational flow without clear consent and handling guarantees materially increases the risk of credential leakage or misuse.
The documentation creates an explicit workflow where the model solicits a sensitive API key from the user and persists it locally. In the context of an agent skill, this is dangerous because secrets can be captured in conversation logs, written to insecure storage, or reused outside the user's immediate intent.
The documentation states that code only calls APIs, but the workflow also requires saving a user-provided API key locally via configuration. This is a security-relevant omission because credential persistence changes the threat model from transient use to retention and possible later exposure.
The skill tells the model to directly display result['raw'] from the API response after simple formatting. Raw upstream responses may include sensitive content, debugging metadata, tokens, identifiers, or unexpected fields, so unreviewed passthrough creates a data exposure risk.
Manifest 将该技能描述为动态提示生成与模板组装服务,但此文件实现了将 API key 写入 .env 文件、更新进程环境变量并维护全局凭据状态的能力。这不是该描述下显而易见的提示生成实现细节,而是本地凭据持久化与配置修改行为。
save_api_key_to_env 会读取并重写 .env 文件,同时写入 os.environ,这为技能增加了本地敏感配置持久化能力。对于一个以提示生成和模板组装为目的的技能而言,此类凭据存储/修改能力并非其核心功能所直接需要。
The function writes the API key in plaintext to a local .env file and also exports it into the current process environment without any confirmation, warning, or permission checks. In shared workspaces, developer machines, containers, or repos where .env files may be copied, backed up, or accidentally committed, this can expose credentials and enable unauthorized API use.
The skill's mandatory operational instructions and safety-critical setup steps are presented in Chinese, while the tool descriptions are partly in English, and there is no indication that users may choose their preferred language. This can amount to a language/locale policy issue because the skill effectively imposes a language for critical interaction without opt-in.
The dependency is specified with a lower bound only (requests>=2.31.0), which makes builds non-reproducible and allows future installs to pull in unexpected versions. In a security-sensitive prompt-generation service, this increases supply-chain risk and makes it harder to verify whether a deployed version includes known fixes or newly introduced vulnerabilities.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
requests has known security advisories, but because the manifest does not pin an exact version, it is impossible to verify whether deployments are using a fixed or affected release. This creates supply-chain uncertainty: some environments may resolve to safe versions while others may pull vulnerable ones, undermining security assurance.
pydantic>=2.7.0 is unpinned, so installations may resolve to different versions over time. This weakens reproducibility and can silently introduce vulnerable or incompatible releases into the service, especially important for software that processes dynamic prompts and configuration data.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
pydantic has published advisories, and the lack of version pinning means the actual installed version cannot be audited from this file alone. Since this library is central to data validation and settings parsing, uncertainty about its version weakens confidence in input-handling safety and patch status.
pydantic-settings>=2.2.0 allows any newer version to be installed, preventing certainty about the exact code running in production. For configuration-loading libraries, this is risky because security behavior around environment variables, secret handling, and filesystem access can change across releases.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
pydantic-settings has at least one known advisory, but the unpinned requirement prevents determining whether the installed package is affected. Because this package may interact with secrets and local filesystem-based configuration sources, version ambiguity is a meaningful security hygiene issue in a service context.
python-dotenv>=1.0.1 is not pinned, so the environment-loading component may vary between installations. Because dotenv tooling influences how configuration and secrets are read from files, unbounded upgrades can expose the service to regressions or vulnerable behaviors without explicit review.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
python-dotenv has known advisories and is not pinned, so the security posture of deployed instances cannot be confirmed from this manifest. In services that may load environment files during startup or local development, uncertainty around file-handling behavior can translate into avoidable configuration or filesystem risk.