T09 · Insecure Skill Coding Practices
- Location
scripts/connection_manager.py:85- Finding
Database Credentials Are Persisted in Plaintext Without Explicit Access Controls
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This SQL helper matches its stated purpose, but it under-discloses serious risks around database credentials, read-only enforcement, and sending query results to an external model.
Review carefully before installing. Use only test or read-only database accounts, avoid production credentials, avoid saving passwords through this skill, and assume schema details, query text, and some result values may be sent to the configured model provider. Do not rely on the advertised read-only or parameterized-query protections without code fixes and database-side read-only permissions.
scripts/connection_manager.py:85Database Credentials Are Persisted in Plaintext Without Explicit Access Controls
scripts/connection_manager.py:20Remote Database Credentials May Be Transmitted Without Enforced TLS
scripts/insight_generator.py:11Raw Database Records Are Embedded in Model-Facing Insight Prompts
scripts/executor.py:8Read-Only SQL Enforcement Is Broken and Fails Open for Unknown Statements
scripts/security.py:138Sensitive Schema Masking Is Unused and Can Preserve Sensitive Names
scripts/nl_parser.py:134Untrusted Queries and Database Metadata Can Inject Instructions Into LLM Prompts
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.
Undeclared live connectivity to local or remote databases expands the attack surface and can expose internal services, credentials, or metadata, especially when users believe the skill is mostly an offline SQL assistant. If safe execution and NL→SQL are also unimplemented, remote access combined with false assurances raises operational risk.
Undeclared live connectivity to local or remote databases expands the attack surface and can expose internal services, credentials, or metadata, especially when users believe the skill is mostly an offline SQL assistant. If safe execution and NL→SQL are also unimplemented, remote access combined with false assurances raises operational risk.
Undeclared live connectivity to local or remote databases expands the attack surface and can expose internal services, credentials, or metadata, especially when users believe the skill is mostly an offline SQL assistant. If safe execution and NL→SQL are also unimplemented, remote access combined with false assurances raises operational risk.
Undeclared live connectivity to local or remote databases expands the attack surface and can expose internal services, credentials, or metadata, especially when users believe the skill is mostly an offline SQL assistant. If safe execution and NL→SQL are also unimplemented, remote access combined with false assurances raises operational risk.
Undeclared live connectivity to local or remote databases expands the attack surface and can expose internal services, credentials, or metadata, especially when users believe the skill is mostly an offline SQL assistant. If safe execution and NL→SQL are also unimplemented, remote access combined with false assurances raises operational risk.
Undeclared live connectivity to local or remote databases expands the attack surface and can expose internal services, credentials, or metadata, especially when users believe the skill is mostly an offline SQL assistant. If safe execution and NL→SQL are also unimplemented, remote access combined with false assurances raises operational risk.
Undeclared live connectivity to local or remote databases expands the attack surface and can expose internal services, credentials, or metadata, especially when users believe the skill is mostly an offline SQL assistant. If safe execution and NL→SQL are also unimplemented, remote access combined with false assurances raises operational risk.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
Save a named connection configuration.
Passwords are stored with basic obfuscation (not encryption).
For production, use environment variables or system keychain.
"""
os.makedirs(DATA_DIR, exist_ok=True)
The module advertises 'safe', 'read-only by default', and 'parameterized queries', but the implementation does not reliably enforce those guarantees. In particular, the read-only gate is broken because the code imports is_read_only_query directly but calls security.is_read_only_query(sql), which would fail and undermine the intended protection, while other paths still execute raw SQL against live databases.
The documentation claims parameterized queries, but all execution paths pass raw SQL strings directly to cursor.execute(sql), and the EXPLAIN helpers interpolate user-controlled SQL into f"EXPLAIN ... {sql}". In a natural-language-to-SQL skill, this materially increases the risk that untrusted model- or user-generated SQL is executed directly, enabling injection of stacked statements or dangerous commands depending on driver and database behavior.
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
Keep it concise and actionable."""
return prompt
def _detect_language(query: str) -> str:
The function constructs and returns a raw LLM prompt that directly embeds untrusted user input (query) and schema_text into the instruction context. In an NL-to-SQL skill, this creates a prompt-injection surface where a crafted natural-language query can try to override the read-only rules, exfiltrate schema details, or induce unsafe SQL generation if downstream controls rely mainly on the model following prompt instructions.
SQL:"""
return prompt
def extract_query_summary(query: str) -> str:
The module claims read-only enforcement, but is_read_only_query() returns True for any statement that is neither explicitly matched as write nor recognized as read. That fail-open behavior can permit dangerous dialect-specific or procedural statements, especially in a tool that converts natural language into SQL and may execute the result automatically.
The skill advertises capabilities that imply file access, local credential storage, and remote database/network connectivity, but it declares no explicit tool scope or permission boundaries. In an agent environment, missing scope declarations can cause over-privileged execution or make reviewers unable to verify whether database, filesystem, and network access are intentionally constrained.
Selecting an external model/provider introduces data-governance and privacy risk because prompts may include schema metadata, connection details, or operational context sent to a third party. In a SQL assistant, even if row data is excluded, table names, column names, and query text can still reveal sensitive business structure or security-relevant information.
author: Golden Bean (coder)
category: Developer Tools
description: Convert natural language to SQL, explore database schemas, execute queries safely, and get optimization suggestions.
model: deepseek/deepseek-v4-flash
input_schema: schemas/input.schema.json
output_schema: schemas/output.schema.json
---
The options table sets --language default to zh-CN, which means the skill will prefer a specific locale unless the user overrides it. This is a natural-language policy concern because the file does not indicate that the user is first asked to choose a language or explicitly opt in to Chinese as the default.
The schema restricts the language to zh-CN or en-US and defaults to zh-CN, which imposes a specific locale when the user does not explicitly choose one. This is a natural-language policy concern because the file does not indicate user opt-in or a justified region-specific requirement.
The docstring claims passwords are stored with basic obfuscation, but the implementation writes the full connection config, including plaintext passwords, directly to a JSON file under the user's home directory. This creates a credential exposure risk if local files are read by other local users, malware, backups, or support tooling, and the misleading documentation may cause users to underestimate that risk.
The function silently persists connection configurations, including credentials, to disk with no warning or explicit opt-in at the point of storage. In a tool designed to handle database access, this is more dangerous because users may paste production credentials expecting ephemeral use, while the skill retains them locally, increasing the chance of unintended credential retention and later compromise.
This code file performs live database operations in the _explain_* helpers by connecting to SQLite, PostgreSQL, and MySQL and executing EXPLAIN statements, but these functions have no warning, confirmation, or user-facing log indicating that a real database will be contacted. While EXPLAIN is typically read-only, it still touches external systems and may have operational impact, so the absence of disclosure meets the missing-warning criterion for code files.
The prompt embeds raw user query text, generated SQL, column names, sample row values, and numeric summaries directly into content intended for an LLM. In a SQL assistant context, this can expose sensitive database contents or internal query details to a downstream model or logging pipeline without minimization, redaction, or explicit disclosure, increasing data leakage risk.
The function explicitly serializes database schema metadata into prompt text for an LLM, including table names, column names, defaults, comments, foreign keys, and indexes. Even without row data, schema details can disclose sensitive business structure, PII-related fields, secrets-adjacent columns, or internal system design, and in this skill context the output is specifically intended to leave the database boundary and be sent to a model.
Unknown SQL statements are allowed by default with only a server-side warning log, not a blocking control or clear user-facing rejection. In this skill's context, where LLM-generated SQL may vary by dialect and include uncommon commands, this increases the chance that unsafe statements slip past the supposed read-only guardrail.
The code constructs a prompt from the raw natural-language query and full schema text for transmission to an external LLM, but provides no consent flow, redaction, minimization, or user-visible warning that potentially sensitive schema and query contents may leave the local trust boundary. In a SQL assistant, schema metadata can reveal table names, business structure, and sensitive domains, while user queries may contain confidential identifiers or investigative context, making this a real data-exposure risk even if no direct code execution occurs.
No suspicious patterns detected.