Back to skill

Security audit

Vibe Coding 可行性评估

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but its API-key handling can send an OpenAI key to DeepSeek by default and it does not clearly disclose the external data flow.

Review before installing. Use only a DeepSeek key unless the provider selection is fixed, do not run it in an environment containing unrelated OPENAI_API_KEY values, and avoid submitting confidential product plans, customer data, internal architecture, or secrets in the idea text until the skill clearly discloses and constrains its external API data flow.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/evaluate_vibe.py:5
Finding
OpenAI API Key May Be Transmitted to the Default DeepSeek Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/evaluate_vibe.py`, lines 5-18 **Vulnerability Type**: Provider credential and endpoint mismatch **Risk Level**: High ### Vulnerable Code ```python API_KEY = os.environ.get("OPENAI_API_KEY") or os.environ.get("DEEPSEEK_API_KEY", "") API_BASE = os.environ.get("OPENAI_API_BASE", "https://api.deepseek.com") MODEL = os.environ.get("LLM_MODEL", "deepseek-chat") def call_llm(prompt): if not API_KEY: return "[错误] 请设置 OPENAI_API_KEY 或 DEEPSEEK_API_KEY" payload = json.dumps({"model": MODEL, "messages": [ {"role": "system", "content": "你是一位资深 AI 编程工具专家,深度使用过 Cursor、Windsurf、Bolt、v0、Replit AI 等工具。你能准确评估哪些任务适合 vibe coding,哪些需要人工介入。请用中文回答,使用 Markdown 格式。"}, {"role": "user", "content": prompt} ], "temperature": 0.7}).encode() req = urllib.request.Request(f"{API_BASE}/chat/completions", data=payload, headers={"Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}"}) with urllib.request.urlopen(req, timeout=60) as r: ``` ### Technical Analysis The credential-selection logic and endpoint-selection logic are not coupled to the same provider. `OPENAI_API_KEY` is selected before `DEEPSEEK_API_KEY`, but the default API endpoint is `https://api.deepseek.com`. Consequently, when `OPENAI_API_KEY` exists and `OPENAI_API_BASE` is absent, the program places the OpenAI credential in an HTTP bearer authorization header and transmits it to DeepSeek. The independently configurable API base can also cause a selected credential to be sent to another unintended endpoint if the environment is incorrectly or maliciously configured. The HTTPS connection protects the credential in transit from passive network interception, but it does not prevent the destination server from receiving and retaining the bearer credential. ### Attack Path 1. An OpenAI API credential is present in the process environment as `OPENAI_API_KEY`. 2. `OPENAI_API_BASE` is unset, so the ap ...[truncated 1236 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Couple each credential explicitly to its provider endpoint: - Use `OPENAI_API_KEY` only with a validated OpenAI endpoint. - Use `DEEPSEEK_API_KEY` only with a validated DeepSeek endpoint. 2. Do not silently prioritize one provider's key while defaulting to another provider's service. 3. Introduce an explicit provider setting, such as `LLM_PROVIDER=openai` or `LLM_PROVIDER=deepseek`, and derive the key, endpoint, and default model from that selection. 4. Reject conflicting configurations, including multiple provider keys without an explicit provider selection. 5. Validate the destination host against an allowlist before attaching an authorization header. Require a separate, explicit opt-in for custom endpoints. 6. Fail closed when the selected key does not match the configured provider or endpoint. 7. Document that the project description and skill-level input are transmitted to an external LLM service. 8. Revoke and rotate any OpenAI credential that may already have been transmitted to the default DeepSeek endpoint. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Tainted flow: 'req' from os.environ.get (line 16, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
], "temperature": 0.7}).encode()
    req = urllib.request.Request(f"{API_BASE}/chat/completions", data=payload,
        headers={"Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}"})
    with urllib.request.urlopen(req, timeout=60) as r:
        return json.loads(r.read())["choices"][0]["message"]["content"]

def build_prompt(idea, skill_level):
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill invokes a Python script and the static analysis indicates code capabilities including environment access and network use, but the manifest does not declare any tool scope such as permissions or allowed-tools. That creates an overbroad execution surface where the runtime may grant more capability than the skill documentation communicates, making unintended data access or outbound requests harder to review and contain.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The entire skill description and examples are presented only in Chinese, with no indication that users may interact in other languages or choose their preferred locale. Under the policy, language constraints should either be optional for the user or clearly documented as justified for a specific regional use case.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The phrase '描述你想做的功能或项目,我帮你评估' is a very general invitation that could overlap with many ordinary project-discussion requests. The document provides example prompts, but it does not clearly define specific trigger phrases, scope constraints, or negative examples to distinguish when this skill should activate versus when a general assistant should respond.

Context-Inappropriate Capability

Medium
Confidence
89% confidence
Finding
该技能会读取环境变量中的 API 凭证并向外部 LLM 服务发送请求,但描述中仅说明“快速评估可行性”,没有明确披露会进行外部网络调用和使用本地凭证。对使用者而言,这会造成能力边界不透明,可能在不知情情况下消耗第三方账户额度,或在受限环境中违反数据/网络使用预期。

Missing User Warnings

Medium
Confidence
94% confidence
Finding
用户输入的项目描述和技能水平会被直接发送到远程 LLM,但程序没有任何用户可见的提示、确认或敏感信息警告。项目描述中常包含未发布产品想法、内部架构、客户需求或密钥片段,这会导致无意的数据外传和合规风险;在该技能场景下,这种风险与其处理自由文本项目需求的上下文高度相关,因此更值得关注。

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The system message explicitly instructs the model to answer in Chinese, which imposes a language choice regardless of user preference. The file does not offer a language option or indicate that this is a region-specific tool with a justified locale constraint.

Static analysis

No suspicious patterns detected.