T09 · Insecure Skill Coding Practices
- Location
scripts/call_api.py:51- Finding
Configurable API Endpoint Can Expose Credentials and Scan Data
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This BBOT scanner wrapper needs review because it asks for and stores an external service API key while carrying unrelated XiaoBenYang/Gaokao configuration and proxying scan data to a configurable external endpoint.
Install only if you trust the XiaoBenYang service and understand that your API key and scan targets/options will be sent to that external API. Use it only for systems you are authorized to scan, avoid storing sensitive keys in a shared workspace .env file, and review or constrain the base URL and dependency versions before use.
scripts/call_api.py:51Configurable API Endpoint Can Expose Credentials and Scan Data
scripts/config.py:42API Key Is Persisted in a Predictable Plaintext File Without Enforced Access Controls
requirements.txt:1Unbounded Dependency Versions Allow Unreviewed Future Releases
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.
The skill presents itself as a BBOT scanner but references configuration and API-key handling for an unrelated service/project, including .env persistence and non-BBOT settings. This is especially risky in a security-scanning context because users may provide credentials or authorize actions believing they are for BBOT operations when they are actually for a different external service.
The skill presents itself as a BBOT scanner but references configuration and API-key handling for an unrelated service/project, including .env persistence and non-BBOT settings. This is especially risky in a security-scanning context because users may provide credentials or authorize actions believing they are for BBOT operations when they are actually for a different external service.
The documentation for a BBOT security-scanning skill is contradicted by instructions to collect and store an API key for a different service. Contradictory instructions around credentials are dangerous because they create a phishing-like pattern: the user is asked for a secret that is not clearly necessary for the advertised function.
The workflow example references school-search behavior and generic API passthrough rather than BBOT-specific scanning logic, showing the skill instructions were likely copied from another domain. This mismatch makes the skill less trustworthy and increases the likelihood of unsafe routing, incorrect tool use, and accidental disclosure of user inputs to irrelevant backends.
The file claims to belong to a BBOT security scanning service, but the code and comments are clearly for a different product ('小笨羊高考') and use unrelated identifiers such as XBY_GAOKAO_ and xiaobenyang.com. This mismatch is a strong supply-chain integrity concern because operators may believe they are deploying BBOT functionality while actually loading code tied to another service and credential namespace.
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 explicitly reads the .env file itself and extracts XBY_APIKEY outside the normal settings flow, creating an additional secret-handling path that may bypass expected validation and auditability. In the context of a security-scanning skill, extra credential collection logic is more sensitive because operators may grant elevated trust and provide privileged tokens.
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")
Checking for and reading a local .env file is not malicious by itself, but here it is part of explicit credential extraction logic targeting XBY_APIKEY. This enlarges the attack surface for secret exposure and makes it easier for unrelated code in the package to harvest credentials from disk.
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 writes the API key into a plaintext .env file, creating a durable secret at rest that may be readable by other local users, backups, tooling, or accidentally committed to source control. Because this is packaged as a security-related service, users may supply sensitive scanner credentials, making plaintext persistence especially risky.
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 networked API calls. In an agent setting, missing scope declarations increase the chance of over-privileged execution and make it harder for users or platforms to constrain sensitive actions like credential storage and outbound requests.
The skill can initiate active security scans against user-specified targets but does not include a clear warning, authorization check, or consent language before launching scans. In a security tool context, that omission is important because active scanning can be disruptive, unauthorized, or legally sensitive if run against systems the user does not control.
The instruction to directly present result["raw"] to the user can expose sensitive information returned by the backend, including user-submitted targets, tokens, internal metadata, or scan artifacts that were not meant for broad display. In a networked scanning tool, raw backend responses frequently contain more detail than should be surfaced verbatim.
The documented project structure names a different project and external API client components, contradicting the claimed BBOT identity of the skill. In aggregate with the other inconsistencies, this materially increases the risk that users are interacting with a mislabeled wrapper that sends data or secrets to an unintended backend.
This code accesses a sensitive credential via get_api_key() and transmits it in the XBY-APIKEY header during the outbound POST request. Although errors and successes are logged, there is no confirmation prompt, user-facing notice, or explanatory comment/docstring warning that a credential will be used and sent to an external service.
The helper persists API keys directly into a local .env file and also exports them into the process environment without any warning, consent flow, or file-permission hardening. This increases the chance of secret exposure through source control, backups, local file disclosure, or accidental sharing on multi-user systems.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
modules: Comma-separated list of modules to use (optional)
presets: Comma-separated list of presets to use (optional)
flags: Comma-separated list of flags to use (optional)
no_deps: Disable dependency installation to prevent sudo prompts (default: True)
Args:
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
modules: Comma-separated list of modules to use (optional)
presets: Comma-separated list of presets to use (optional)
flags: Comma-separated list of flags to use (optional)
no_deps: Disable dependency installation to prevent sudo prompts (default: True)
Args:
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
modules: Comma-separated list of modules to use (optional)
presets: Comma-separated list of presets to use (optional)
flags: Comma-separated list of flags to use (optional)
no_deps: Disable dependency installation to prevent sudo prompts (default: True)
Args:
The dependency is specified with a lower bound only, so builds may resolve to different versions over time. This weakens supply-chain control, makes security posture non-reproducible, and can accidentally introduce vulnerable or breaking releases.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Requests has multiple known advisories, and because the manifest does not pin a version, it is impossible to verify whether deployed environments avoid affected releases. In a network-facing security scanning service, an unresolved HTTP client dependency can materially increase exposure to credential leakage or TLS/request-handling flaws.
The dependency is specified with a lower bound only, so installations are not reproducible and may pull in unexpected future versions. In a security-oriented service, this increases supply-chain risk because behavior and vulnerability exposure can change without code changes.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
Pydantic has published advisories, and the unpinned version prevents confirming whether the installed release is patched. This creates avoidable uncertainty in a core parsing/validation library that could expose denial-of-service or input-handling weaknesses.
Using an unpinned version allows the installed pydantic-settings release to vary across environments and over time. That makes it harder to verify whether known advisories are addressed and increases the chance of pulling a risky release.
requests>=2.31.0
pydantic>=2.7.0
pydantic-settings>=2.2.0
python-dotenv>=1.0.1
No suspicious patterns detected.