Back to skill

Security audit

万能祝福语生成器

Security checks for vulnerabilities and agentic risk

Overview

This blessing generator is purpose-aligned, but it needs Review because it can send personal prompt details and an API key to an unvalidated or mismatched remote LLM endpoint.

Review before installing. Use this only if you are comfortable sending greeting prompts, recipient descriptions, relationship details, and recent-life context to the configured LLM provider. Avoid sensitive personal information. If you run it, set a matching provider credential and endpoint deliberately, and prefer a patched version that validates trusted HTTPS hosts, couples each API key to its provider, and clearly discloses remote processing.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_blessing.py:5
Finding
API credential may be transmitted to the wrong or untrusted provider## Vulnerability Details **File Location**: `scripts/generate_blessing.py:5-6` and `scripts/generate_blessing.py:54-57` **Vulnerability Type**: Provider/credential mismatch and insufficient endpoint validation **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") ``` ```python payload = json.dumps({"model": MODEL, "messages": [ {"role": "system", "content": "你是一位擅长写祝福语的文字高手,能够根据不同节日、不同对象、不同风格生成有温度、有个性的祝福语。请用中文输出。"}, {"role": "user", "content": prompt} ], "temperature": 0.9}).encode() req = urllib.request.Request(f"{API_BASE}/chat/completions", data=payload, headers={"Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}"}) ``` ### Technical Analysis Credential selection is independent of API endpoint selection. The script gives `OPENAI_API_KEY` precedence, while the default endpoint is DeepSeek. Therefore, when `OPENAI_API_KEY` is defined and `OPENAI_API_BASE` is not, the script sends the OpenAI credential to `https://api.deepseek.com`. In addition, `OPENAI_API_BASE` is accepted without validation. A modified process environment can redirect requests to an arbitrary endpoint, including a server controlled by an attacker or an unencrypted HTTP endpoint. The selected API key is always placed in the `Authorization` header sent to that endpoint. ### Attack Path 1. The execution environment contains a valid `OPENAI_API_KEY`. 2. `OPENAI_API_BASE` is either unset or changed to an unintended endpoint. 3. The user runs the documented blessing-generation command. 4. The script selects `OPENAI_API_KEY`. 5. It sends that key in the Bearer authorization header to the default DeepSeek endpoint or the configured untrusted endpoint. 6. The recipient can capture and attempt to use the exposed credential. ### Impact Assessment A discl ...[truncated 337 chars]
Remediation
## Remediation Suggestions - Couple each credential to its corresponding provider and endpoint. - Use `DEEPSEEK_API_KEY` when the endpoint is DeepSeek, and use `OPENAI_API_KEY` only for an explicitly selected OpenAI endpoint. - Require explicit provider selection rather than inferring it from unrelated environment variables. - Validate the endpoint with a strict allowlist of trusted HTTPS origins. - Reject plaintext HTTP, embedded credentials, unexpected ports, redirects to untrusted origins, and unknown hosts. - If custom endpoints are required, place them behind an explicit opt-in flag and clearly warn that the credential will be sent to that host. - Use provider-specific environment variables such as `DEEPSEEK_API_BASE` and `OPENAI_API_BASE`. - Avoid forwarding authorization headers across redirects to a different origin. A safer configuration pattern would select the provider first, then load only that provider's endpoint and credential. The program should terminate with an error if the selected provider, endpoint, and credential do not match.

other

Note
Location
scripts/generate_blessing.py:54
Finding
Personal context is transmitted to a remote LLM without clear disclosure## Vulnerability Details **File Location**: `scripts/generate_blessing.py:54-57`, `scripts/generate_blessing.py:73-74`, and `scripts/generate_blessing.py:96-100` **Vulnerability Type**: Undisclosed external transmission of user-provided personal information **Risk Level**: Low ### Vulnerable Code ```python payload = json.dumps({"model": MODEL, "messages": [ {"role": "system", "content": "你是一位擅长写祝福语的文字高手,能够根据不同节日、不同对象、不同风格生成有温度、有个性的祝福语。请用中文输出。"}, {"role": "user", "content": prompt} ], "temperature": 0.9}).encode() req = urllib.request.Request(f"{API_BASE}/chat/completions", data=payload, headers={"Content-Type": "application/json", "Authorization": f"Bearer {API_KEY}"}) ``` ```python recent_hint = f"\n对方近况:{recent}(请在祝福中融入这些信息,使祝福更个性化)" if recent else "" ``` ```python parser.add_argument("--target", default="朋友", help="祝福对象称呼,如:妈妈/老板/闺蜜") parser.add_argument("--relation", default="平辈", help="关系:长辈/平辈/晚辈/上级/客户") parser.add_argument("--recent", default="", help="近况关键词,如:升职/刚失恋/生了宝宝") parser.add_argument("--style", default="温情", help="风格:正式/温情/幽默/文艺/押韵/简短") parser.add_argument("--length", default="medium", help="字数:short/medium/long") ``` ### Technical Analysis Values supplied through `--target`, `--relation`, and `--recent` are incorporated into the generated prompt. The entire prompt is then sent to the configured remote chat-completions endpoint. The `--recent` option explicitly encourages users to enter personal circumstances, such as relationship changes, promotions, or childbirth. Recipient names or other identifying details may also be supplied through `--target`. Neither `README.md` nor `SKILL.md` clearly informs users that these values leave the local machine and are processed by an external LLM provider. ### Attack Path 1. A user supplies a recipient identifier or sensitive life circumstance through `--target` or `--recent`. 2. `build_prompt` embeds that information in the LLM pro ...[truncated 799 chars]
Remediation
## Remediation Suggestions - Clearly disclose in `README.md`, `SKILL.md`, and CLI help that prompt content is transmitted to an external LLM provider. - Identify the default provider and explain that custom endpoint configuration changes the data recipient. - Warn users not to provide secrets, full names, medical details, financial information, or other sensitive personal data. - Obtain explicit confirmation before the first remote submission or provide a dedicated non-interactive consent flag. - Display the destination host before transmitting data. - Minimize transmitted information and avoid including fields that are unnecessary for generation. - Offer local redaction or pseudonymization for recipient names and sensitive circumstances. - Document applicable provider retention and privacy policies. - Consider a local-model mode for users who cannot transmit personal information to external services.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (8)

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

Critical
Category
Data Flow
Content
], "temperature": 0.9}).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(festival, target, relation, recent, style, length_hint):
Confidence
97% confidence
Finding
The code builds the request destination and authorization header from environment-controlled values and sends them via urllib to whatever API_BASE is configured. If API_BASE is changed to a malicious or unintended host, the bearer token and all user-supplied blessing context are exfiltrated to that endpoint, creating an SSRF/credential-leakage risk.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises a Python tool invocation and static analysis detected environment and network capabilities, but the manifest declares no explicit tool scope or permissions boundary. This creates an unclear trust boundary: a host may permit broader execution than users expect, increasing the risk of unintended data access, outbound requests, or abuse if the backing script changes or is compromised.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The display name, description, usage examples, parameters, and output format are all presented only in Chinese, implying the skill is intended to operate in a single language. The file does not state that Chinese is optional, nor does it offer a user-selectable language or locale choice.

Vague Triggers

Medium
Confidence
83% confidence
Finding
This markdown file describes supported activation scope for custom occasions as 'anything you want to celebrate,' which is ambiguous and lacks boundaries or exclusion examples. That broad natural-language trigger can overlap with many ordinary requests and makes it unclear when the skill should or should not be invoked.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The manifest describes a skill that takes recipient/festival/style information and generates personalized blessings, but it does not disclose any external service integration or credential use. The code reads API keys from environment variables and sends all user inputs over HTTP to a third-party chat completions endpoint, which is a materially broader capability than the stated purpose implies.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The system prompt explicitly instructs the model to '请用中文输出', which imposes a fixed language policy. There is no indication elsewhere in the file that the user can opt into another language or that the Chinese-only constraint is required for a region-specific purpose.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The CLI accepts personal context such as relationship, recent life events, and recipient details, then transmits that data to an external LLM without any explicit user warning or consent flow. This can expose sensitive personal information unexpectedly, especially when users include health, relationship, family, or work details in the recent field.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The skill description, examples, and parameter values are entirely presented in Chinese, which effectively constrains interaction to a specific language. The file does not indicate that other languages are supported or that Chinese is an intentional, opt-in locale choice.

Static analysis

No suspicious patterns detected.