T09 · Insecure Skill Coding Practices
- Location
scripts/sql_easy.py:580- Finding
API Credential and Database Schema Disclosure Through an Unrestricted LLM Endpoint
- Content
View full analysis
Vulnerability Details
File Location:
scripts/sql_easy.py, lines 115-116 and 580-605
Vulnerability Type: Unrestricted transmission of sensitive information to a configurable network endpoint
Risk Level: HighVulnerable Code
python p_ask.add_argument("--api-key", default=os.getenv("OPENAI_API_KEY", ""), help="LLM API key.") p_ask.add_argument("--base-url", default=os.getenv("OPENAI_BASE_URL", "https://api.openai.com"), help="LLM API base URL.")python def call_openai_chat(prompt: str, model: str, api_key: str, base_url: str) -> str: if not api_key: raise SqlEasyError( "Missing OPENAI_API_KEY. Set environment variable or pass --api-key for `ask` command." ) url = base_url.rstrip("/") + "/v1/chat/completions" payload = { "model": model, "temperature": 0, "messages": [ {"role": "system", "content": "Generate safe SQL in JSON output only."}, {"role": "user", "content": prompt}, ], } body = json.dumps(payload).encode("utf-8") req = urlrequest.Request( url=url, data=body, headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, method="POST", ) try: with urlrequest.urlopen(req, timeout=60) as resp: resp_payload = json.loads(resp.read().decode("utf-8"))The transmitted prompt is populated with database schema metadata and the user’s question:
python schema_context = build_schema_context(client, max_tables=max_tables, max_columns=max_columns) if not schema_context.strip(): raise SqlEasyError("Schema discovery returned empty result; cannot generate SQL safely.") prompt = build_nl2sql_prompt(question=question, dialect=client.dialect, schema_context=schema_context) raw = call_openai_chat(prompt=prompt, model=model, a ...[truncated 2540 chars]- Remediation
View remediation
Remediation Suggestions
- Require an
https://URL and reject plaintext HTTP or unsupported schemes before constructing the request. - Allowlist trusted LLM hosts by default, such as the documented provider endpoint.
- Do not send an
OPENAI_API_KEYto a non-OpenAI host. Custom providers should use separate, provider-specific credentials. - Require explicit user confirmation before sending schema metadata to a custom endpoint.
- Display the destination host and a concise description of the data being transmitted before the first request.
- Document clearly in
SKILL.mdthatasktransmits table names, column names/types, SQL dialect, and the user’s question to an external service. - Provide options to redact identifiers, select specific tables, or operate with a manually supplied minimal schema.
- Consider certificate pinning or organization-controlled proxies in higher-assurance deployments.
- Avoid passing API keys on the command line where they may be exposed through shell history or process listings; prefer protected environment variables or a credential manager.
- Require an
