T09 · Insecure Skill Coding Practices
- Location
scripts/config.py:10- Finding
Configurable API Endpoint Can Expose API Keys and Image Data
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This gesture-detection skill appears to use a remote API as intended, but it stores API keys in a local plaintext .env file and allows endpoint configuration that could redirect sensitive image data and credentials.
Review before installing. Use only if you are comfortable sending image URLs or full base64 image data to Xiaobenyang and storing the API key in a local plaintext .env file. Prefer a dedicated low-privilege API key, avoid sensitive images, check the .env file contents and permissions, and do not run this in a workspace where untrusted files or environment variables can alter the API base URL.
scripts/config.py:10Configurable API Endpoint Can Expose API Keys and Image Data
scripts/config.py:44API Key Is Persisted in a Plaintext Workspace File Without Explicit Permission Hardening
The skill claims to perform image analysis but also reads from .env, persists API keys, manages base URLs and retry settings, and includes credential-management helpers unrelated to gesture detection. This broad hidden functionality increases the attack surface and can expose users to credential mishandling or unauthorized reconfiguration of remote destinations.
The skill claims to perform image analysis but also reads from .env, persists API keys, manages base URLs and retry settings, and includes credential-management helpers unrelated to gesture detection. This broad hidden functionality increases the attack surface and can expose users to credential mishandling or unauthorized reconfiguration of remote destinations.
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 model_post_init function force-reads a local .env file to extract XBY_APIKEY outside normal typed settings flow, creating custom secret-harvesting logic not justified by the declared skill. In context, this is more dangerous because the skill ostensibly performs local image gesture detection, so collecting and persisting unrelated credentials is unexpected and broadens attack surface.
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")
Creating a Path to .env and reading it as part of custom initialization contributes to unauthorized or unnecessary credential access behavior in this skill's context. Even if intended for convenience, this behavior can expose secrets from local developer environments and is inconsistent with a narrowly scoped image-detection tool.
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 hand-gesture detection skill includes logic to persist and manage an external API key in local files and process environment, which is unrelated to the declared image-analysis purpose. Such credential-handling expands the trust boundary, creates secret exposure risk on disk, and is especially suspicious because the file also references a different product/domain than the manifest.
The code writes user-supplied credentials to a local .env file and modifies process environment variables, capabilities that are unjustified for a simple gesture-detection skill. This can leave secrets recoverable from the filesystem, source bundles, backups, or logs, and increases the chance of unauthorized reuse by other code on the host.
The function explicitly saves an API key to .env, creating persistent plaintext local credential storage. In a skill whose stated purpose is gesture detection, this is unnecessarily dangerous because secrets may be exposed through repository inclusion, backups, local compromise, or reuse by unrelated processes.
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 even though it is documented as using environment access, file reads/writes, and network access. That creates unnecessary privilege and reduces reviewability, making it easier for a seemingly simple image-analysis skill to access credentials, persist secrets, or exfiltrate data through undeclared capabilities.
The skill instructs the agent to collect an API key from the user and persist it via set_api_key without warning that the credential will be stored. This is dangerous because users may disclose sensitive secrets without informed consent, and persistence to local configuration or .env increases the risk of later leakage through file access, backups, or other tools.
The project structure and examples reference a gaokao/school-search skill instead of the declared gesture-detection functionality, indicating copy-paste drift or repurposed code. Such inconsistency is a security concern because it suggests the skill may invoke unrelated logic or hide capabilities that reviewers and users would not expect from the stated purpose.
This code sends the caller-provided params to an external HTTP endpoint and includes an API credential in the request headers. While the behavior is implemented clearly, there is no confirmation prompt, print/log disclosure to the user, or inline warning comment/docstring indicating that user data may be transmitted off-system.
The class docstring describes a different skill domain ('高考' configuration) than the manifest's hand-gesture detection purpose, indicating code reuse, mismatch, or possible repackaging. Context mismatches make security review harder and increase suspicion that hidden or unintended behavior may be present, especially alongside unrelated credential-management code.
The function persists an API key to .env without any visible warning, confirmation, or notice about durability and scope of storage. Users may reasonably expect a transient configuration value, but the code silently creates long-lived local secret exposure that can be read later by other tools or users on the system.
The function sends a user-supplied image URL to an external API service, but this file provides no disclosure, consent flow, or indication of data handling boundaries. Even if the feature requires remote inference, transmitting image content or image references off-platform can expose sensitive visual data and metadata to a third party without the user's awareness.
This function transmits raw base64-encoded image content to an external API, which is a direct transfer of potentially sensitive user data. Because the file contains no warning, consent mechanism, or privacy guardrails, users may unknowingly send biometric or otherwise private visual information to a third-party service.
The entire skill description, prompts, and operating instructions are presented only in Chinese, and there is no statement that users may interact in other languages or that the locale limitation is intentional for a region-specific use case. Under the language/locale policy, forcing a specific language without opt-in can be a natural-language policy issue.
The workflow section claims the model should choose tools for this gesture-detection skill, yet the concrete example demonstrates a school-search call with score/province/category parameters. This is an active contradiction in the documentation because it instructs behavior unrelated to hand-gesture detection.
The dependency is specified with a lower-bound only (requests>=2.31.0), which allows future unresolved versions to be installed and prevents reproducible builds. This increases supply-chain risk because a vulnerable or breaking release could be pulled in without review, and the separate advisory listing for requests makes the uncertainty more relevant.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
requests has multiple known advisories, but the manifest does not pin an exact version, so it is impossible to verify whether deployed environments are using a safe release. In a skill that may make outbound HTTP requests, uncertainty around a network-facing library increases supply-chain and runtime risk.
pydantic>=2.7.0 is unpinned, so installations may resolve to different future versions with unknown security properties. This is a supply-chain hygiene weakness rather than an immediate exploit, but it can expose deployments to newly introduced vulnerable releases.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
pydantic has known advisories, and because only a minimum version is declared, the actual installed version cannot be assessed for exposure. This is dangerous because input-validation libraries are often security-relevant, and a vulnerable version could affect parsing or cause denial of service.
Using pydantic-settings>=2.2.0 without an upper bound or exact pin means the runtime package version is not controlled. That weakens reproducibility and can silently introduce vulnerable or incompatible versions into the skill environment.
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 lack of an exact version means exposure cannot be determined from this file alone. Since settings libraries can read secrets and filesystem paths, unverifiable versions create avoidable uncertainty around secret-handling behavior.