T09 · Insecure Skill Coding Practices
- Location
scripts/config.py:11- Finding
Configurable Upstream Endpoint Can Exfiltrate the API Key
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This chart skill needs Review because it stores an API key locally and sends it to a configurable third-party service while the documentation is inconsistent about what service it actually uses.
Install only if you trust the Xiaobenyang service and are comfortable storing its API key in a plaintext .env file in the working directory. Prefer a disposable or tightly scoped API key, check that XBY_GAOKAO_BASE_URL points only to the intended provider, and rotate the key if the workspace may have been shared, committed, backed up, or collected.
scripts/config.py:11Configurable Upstream Endpoint Can Exfiltrate the API Key
scripts/config.py:45API Key Is Persisted in a Plaintext File Without Enforced Access Controls
The skill claims chart-generation functionality but prominently instructs reading and writing a local .env credential named XBY_APIKEY and points users to a non-Quick-Chart provider. In a security context, undocumented credential collection and local secret persistence under a misleading service identity materially increase the risk of credential misuse, accidental exfiltration, and user deception.
The skill claims chart-generation functionality but prominently instructs reading and writing a local .env credential named XBY_APIKEY and points users to a non-Quick-Chart provider. In a security context, undocumented credential collection and local secret persistence under a misleading service identity materially increase the risk of credential misuse, accidental exfiltration, and user deception.
The documentation mixes chart-generation claims with gaokao/school-search naming and examples, indicating copy-paste residue or incomplete repurposing. Such inconsistent identity is a strong security concern because it undermines operator understanding of what the skill actually does and can hide unrelated network calls or business logic behind an innocuous description.
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",
)
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",
)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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")
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
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")
This function explicitly writes an API key into a plaintext .env file, creating durable local credential storage that can be exposed through file permissions, backups, debugging artifacts, or accidental repository commits. In a chart tool skill, such secret persistence is not inherently required and therefore increases risk without clear justification.
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 permissions despite documented capabilities to read environment state, write configuration, and access the network. That creates an overly broad trust boundary: a reviewer or host cannot easily constrain what the skill may do, and the same document also instructs persistence of user-supplied API keys, increasing the risk of unintended secret handling.
The skill instructions and user-facing documentation are entirely in Chinese, and the workflow does not offer any language choice or state that the skill is region-specific. This can violate language/locale policy because it implicitly forces Chinese-language interaction without explicit user opt-in or documented justification.
The workflow says the code only calls APIs for the chart tool, but the example invocation uses an unrelated search_schools function. Contradictory usage examples can cause downstream agents or reviewers to invoke unintended tools or assume capabilities that were not disclosed, which weakens safe tool routing and least-privilege assumptions.
The class and function docstrings and the returned/raised user-facing messages are written only in Chinese, including the API key setup error and failure message. This creates a natural-language locale constraint without any opt-in or indication that the skill is intentionally region-specific, which fits the language/locale policy violation criteria.
The module persists an API key to a local .env file and updates process environment state, creating durable secret storage on disk beyond transient runtime use. In a chart-service skill, this expands the trust boundary and increases the chance of credential leakage through local file exposure, backups, repository inclusion, or multi-tenant host access.
The code introduces local secret-storage and environment-mutation capability unrelated to the stated chart-generation purpose. This broadens the skill's capabilities to manage credentials on the host, which can surprise users and create avenues for accidental leakage or misuse of stored API keys.
Persisting an API key to .env without any user-facing warning or confirmation causes silent long-term storage of a secret on local disk. This is dangerous because users may reasonably expect a provided key to be used only in-memory, not written to files that can later be read, copied, committed, or recovered.
The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens reproducibility and can unintentionally introduce vulnerable or breaking releases into the skill's environment, especially for a network-facing service that relies on HTTP libraries.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
The manifest does not pin requests, and the package has multiple known advisories across its version history. Because the installed version is not fixed, it is impossible to verify from this file alone whether deployments will receive a safe release, which is risky for a service that communicates with external systems over HTTP.
Using an unpinned pydantic version means deployments may install different releases depending on timing and resolver behavior. That creates supply-chain and stability risk, and could expose the service to known parser or validation issues present in some versions.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
pydantic has known advisories, but the requirements entry leaves the exact installed version unresolved. That makes vulnerability status unverifiable and may allow affected versions to be selected in some environments, particularly when rebuilding or deploying later.
The pydantic-settings package is not pinned, so the environment may drift to newly published versions without explicit review. For configuration-handling libraries, this can matter because parsing or secrets-loading behavior changes may introduce security regressions.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
The pydantic-settings dependency is not pinned despite at least one known advisory affecting some versions. Since this library may load secrets and configuration, leaving the version unresolved increases the chance of deploying an affected release without noticing.
python-dotenv is declared with a minimum version only, allowing uncontrolled upgrades during installation. Because this package handles local environment files, version drift can expose the skill to file-handling or configuration-related vulnerabilities in affected releases.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
python-dotenv has known advisories in parts of its release history, but the requirement does not constrain installation to a verified-safe version. In a service that may read local environment files, this creates uncertainty and avoidable supply-chain exposure.
The manifest names and describes a chart tool service for Quick Chart interaction, but the Settings class docstring says this is configuration for '小笨羊高考Skill'. That directly indicates the file's documentation belongs to a different skill context, creating intent/documentation divergence.
The docstrings, comments, and printed error text are written only in Chinese, which can impose a language choice on users or operators without documented opt-in. The file does not indicate that the skill is intentionally region- or language-specific, nor does it offer an alternative language.
No suspicious patterns detected.