T09 · Insecure Skill Coding Practices
- Location
scripts/config.py:47- Finding
API Key Persisted in a Plaintext File Without Secure Permission or Symlink Controls
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill appears to be a fortune-analysis API wrapper, but it needs review because it stores an API key in plaintext and can send personal birth data and credentials to a configurable remote endpoint.
Review this skill before installing. Only use an API key you are willing to store in a local plaintext .env file, avoid placing the skill in a shared or untrusted working directory, and check that the configured endpoint is the intended XiaoBenYang service before sending birth time, gender, or location data.
scripts/config.py:47API Key Persisted in a Plaintext File Without Secure Permission or Symlink Controls
scripts/call_api.py:50Environment-Controlled API Endpoint Can Receive Credentials and Personal Data
requirements.txt:1Unbounded Dependency Constraints Permit Unreviewed Future Releases
The documented purpose is a fortune-analysis service, but the described behavior includes local .env access, API-key persistence, process environment mutation, and references to a different skill identity ('高考Skill'). That mismatch undermines trust boundaries and suggests users may be prompted for sensitive credentials under a misleading pretext, while the actual implementation does not clearly align with the advertised function.
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 writes the API key into a plaintext .env file, creating persistent credential exposure on disk. In the context of a skill whose actual configured service does not match its manifest, persistent secret capture is more concerning because users may unknowingly save credentials for an unrelated backend.
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 exposes capabilities to read environment variables, read/write local files, and access the network, yet it declares no explicit tool scope or permission boundaries. In this context, the model is instructed to collect and persist an API key into local configuration, so the absence of declared restrictions materially increases the chance of overbroad credential and filesystem access.
This skill requests highly sensitive personal data for fortune analysis, including birth date, time, gender, and potentially location, but it provides no privacy warning, retention notice, or handling guidance. In context, these attributes are personal profile data that can be combined for identification or sensitive inference, especially when sent to a remote API.
The skill explicitly instructs the model to ask the user for an API key and persist it via configuration, creating a natural-language workflow for collecting and storing credentials. This is dangerous because the user may disclose secrets into a conversational channel without clear origin verification, storage guarantees, masking, or least-privilege controls.
The instructions tell the model to directly present raw API response data to the user, which encourages broad disclosure of any fields the backend returns without filtering. In a service handling personal birth data and external API calls, this increases the risk of exposing hidden metadata, internal identifiers, error traces, or other unintended sensitive content.
This code performs an HTTP POST to an upstream service, sending the user-supplied params in the request body and an API key in headers. Although the code logs success and error outcomes, it does not provide a user-facing warning, confirmation, or explanatory comment/docstring that clearly discloses that user or system data will be transmitted to an external service.
The configuration points to xiaobenyang.com and uses XBY_GAOKAO_/XBY_APIKEY identifiers, which conflicts with the advertised 命理分析 service. This mismatch is dangerous because users may provide secrets or invoke actions under false assumptions, enabling credential exfiltration or unauthorized communication with an unrelated external service.
The file identifies itself as a 高考-related skill while the manifest describes a 命理分析 service, which is a meaningful description-behavior mismatch. Such inconsistencies can hide repurposed code, cause operators and users to misunderstand what service they are configuring, and increase the chance that credentials are sent to an unrelated backend.
The code persists the API key directly into a local .env file without any consent flow, warning, permission hardening, or secure storage mechanism. Storing credentials in plaintext increases exposure to accidental commits, local disclosure, backup leakage, or access by other processes/users on the same system.
This function collects sensitive personal data including birth date, gender, and potentially precise location coordinates, then forwards it to a remote API via call_api without any visible consent, disclosure, minimization, or local handling safeguards in this file. In a fortune-analysis context, users may not expect their personal profile and location-derived data to be transmitted off-box, creating privacy and compliance risk if the backend is third-party or logs requests.
This API wrapper sends birth-related personal data and fortune query parameters to an external service without any user-facing warning or consent mechanism shown in this file. Even if not directly exploitable as code execution, it creates a real privacy exposure because sensitive personal attributes are disclosed to a remote system for profiling-style analysis.
The function transmits birth date, gender, and a requested palace analysis target to an external API without visible privacy disclosure in this file. Because astrology/fortune tools inherently process personal profile data, silent remote transfer increases the risk of unauthorized sharing, sensitive inference, or regulatory noncompliance.
This function forwards birth date, gender, and related metadata to a remote API to generate a Bazi chart, with no visible warning or consent flow in the file. Such data can be personally sensitive and may be retained or correlated by the external service, making undisclosed transmission a legitimate privacy vulnerability.
The wrapper sends birth data and query timing information to an external API without any visible user disclosure or indication of third-party processing in this file. In the context of fortune prediction, this enables remote collection of personal profile data that could be used for tracking, inference, or secondary use beyond the user's expectations.
This function submits personal birth information to a remote service for five-element analysis without any visible warning, consent, or privacy boundary in the file. While not an integrity issue, it is a valid privacy/security concern because sensitive personal inputs are exfiltrated to an external processor by default.
Multiple tool definitions hard-code the default language parameter to zh-CN, which imposes a specific locale without documenting user choice or opt-in. The policy allows locale constraints only when justified or when the user is offered a choice, neither of which is stated here.
This tool definition sets language to zh-CN by default, which enforces a locale preference without indicating that the user can choose another language. That creates a natural-language policy issue unless the restriction is clearly justified as region-specific.
The default language value is zh-CN, but the skill text does not say the user may opt into another language or locale. Without user choice or documented justification, this is a locale policy violation.
The language parameter defaults to zh-CN here as well, establishing a mandatory locale preference in the absence of any user opt-in language selection. The file does not document this as a justified regional limitation.
This parameter table again defaults output to zh-CN without offering user language choice in the instructions. Repeated locale forcing across tools violates the stated policy unless clearly justified.