Back to skill

Security audit

liuyao-xueer

Security checks for vulnerabilities and agentic risk

Overview

This divination skill is coherent, but it asks for API keys and can send them with the user's question to any configured server, and the page has an injection bug that could expose those secrets.

Review carefully before installing. Use only low-privilege, disposable API keys with spending limits, do not paste sensitive personal questions, avoid custom endpoints unless you fully trust the destination, and prefer offline mode until the page sanitizes user input and adds clear consent and endpoint validation.

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

Warning
Location
assets/index.html:947
Finding
DOM-Based Cross-Site Scripting Through the Divination Question<![CDATA[ ## Vulnerability Details **File Location**: `assets/index.html`, lines 947–959, 998–1000, and 1037–1058 **Vulnerability Type**: DOM-based cross-site scripting caused by unsafe HTML insertion **Risk Level**: Medium ### Vulnerable Code The user-controlled question is read without sanitization and passed to the result renderer: ```javascript const q=document.getElementById('questionInput').value.trim(); renderDiagram(info,q); ``` The value is subsequently interpolated into markup assigned to `innerHTML`: ```javascript document.getElementById('guaDiagram').innerHTML=` ... <div class="gua-center-label"> <div class="gua-full-name">${info.upper.name}${info.lower.name===info.upper.name?'为'+info.upper.nature:''}卦</div> ${q?`<div class="gua-question-sm">「${q}」</div>`:''} </div> ...`; ``` The offline and request-error paths contain another unsafe HTML sink: ```javascript if(!apiKey){ loading.style.display='none'; out.innerHTML=offlineFallback(info,question); return; } ``` ```javascript out.innerHTML=`<span style="color:#9a5050;font-size:0.82rem">✦ ${err.message}</span>\n\n` +offlineFallback(info,question); ``` `offlineFallback()` includes the untrusted question in its returned string: ```javascript function offlineFallback(info,question){ const q=question?`仙家所问「${question}」,`:''; ... return `这位仙家,${q}六爻落定如下:\n${ys}\n\n` ... } ``` ### Technical Analysis The value from `questionInput` is attacker-controlled. It is embedded into HTML strings and parsed using `innerHTML`, so the browser treats injected tags and event-handler attributes as executable markup rather than plain text. The password input type used for the API key only masks its visual display. JavaScript running in the page can still access its value through the DOM. Consequently, successful script injection can read the configured API key, endpoint, model, question, and generated divination state. The page already demonstrates the safe alternative ...[truncated 1612 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never insert the question into the DOM through `innerHTML`. 2. Construct the result layout with `document.createElement()` and assign the question through `textContent`. 3. Render offline fallback output using: ```javascript out.textContent = offlineFallback(info, question); ``` 4. For the request-error path, create the styled error element separately and assign `err.message` through `textContent`. 5. If HTML formatting is indispensable, sanitize the complete generated markup with a maintained sanitizer configured to reject scripts, event attributes, dangerous URLs, and active embedded content. 6. Add automated tests using HTML tags, event attributes, SVG payloads, malformed markup, and encoded payloads to verify that all question text is rendered literally. 7. Consider clearing the API-key field after use to reduce the period during which injected or unrelated scripts could read it. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
assets/index.html:973
Finding
API Credentials and User Content Can Be Sent to an Arbitrary Configured Origin<![CDATA[ ## Vulnerability Details **File Location**: `assets/index.html`, lines 583–588 and 973–1009 **Vulnerability Type**: Unrestricted sensitive-data transmission to a user-configurable endpoint **Risk Level**: Medium ### Vulnerable Code The page accepts an unrestricted API endpoint alongside an API key: ```html <input type="password" id="apiKey" placeholder="sk-..."/> <input type="text" id="apiBase" value="https://api.openai.com/v1"/> ``` The entered endpoint is used directly as the request destination. The API key is sent in the authorization header, while the question and generated result are included in the body: ```javascript const apiKey =document.getElementById('apiKey').value.trim(); const apiBase=document.getElementById('apiBase').value.trim().replace(/\/$/,''); const modelSel=document.getElementById('apiModel').value; const model=modelSel==='custom'?document.getElementById('customModel').value.trim():modelSel; ``` ```javascript const resp=await fetch(`${apiBase}/chat/completions`,{ method:'POST', headers:{'Content-Type':'application/json','Authorization':'Bearer '+apiKey}, body:JSON.stringify({model,stream:true, messages:[{role:'system',content:sys},{role:'user',content:usr}], temperature:0.75,max_tokens:1800}) }); ``` ### Technical Analysis Custom OpenAI-compatible endpoints are part of the declared functionality, so the request is not covert exfiltration. However, the implementation places full trust in an unrestricted text field. It does not: - Require HTTPS. - Validate the parsed URL or its scheme. - Restrict known providers to their official origins. - Warn the user that the bearer credential and question will be disclosed to the selected origin. - Require confirmation before first sending data to a custom endpoint. - Distinguish credentials intended for different providers. The browser sends the API key to whichever server is specified in `apiBase`. A malicious setup guide, social-engineering message, copied configura ...[truncated 1569 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the endpoint with the `URL` API and reject unsupported schemes. 2. Require HTTPS for remote endpoints. Permit plain HTTP only for explicitly recognized loopback development addresses if necessary. 3. Provide fixed, audited endpoint choices for built-in providers and bind each provider to its official hostname. 4. Treat custom origins as an advanced feature and display a confirmation dialog identifying: - The exact destination origin. - That the API key will be sent in an authorization header. - That the user's question and generated divination data will be sent in the request body. 5. Require separate credentials for each provider rather than silently reusing a key after the destination changes. 6. Clear or invalidate the entered key when `apiBase` is modified. 7. Prefer a trusted backend proxy that uses provider-specific credentials, scoped tokens, spending limits, and server-side destination validation. 8. Apply least-privilege controls to API credentials, including restricted projects, low spending limits, rotation, and short-lived tokens where supported. 9. Consider requiring an explicit “Send for interpretation” action after displaying a summary of the data and destination rather than transmitting automatically when the sixth round completes. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

Hidden Instructions

High
Category
Prompt Injection
Content
<meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>雪儿解卦 · 六爻易经</title>
  <!-- 书法字体 -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&family=ZCOOL+XiaoWei&display=swap" rel="stylesheet">
  <style>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The skill description advertises activation on broad, common terms such as '占卜' and '易经', which can plausibly appear in ordinary conversation or informational queries. Over-broad triggers can cause unintended activation, opening a UI or steering the conversation into the skill unexpectedly, which is a safety and UX control weakness even if not directly malicious.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The activation section lists keywords but provides no boundary rules, disambiguation, or negative cases, making the trigger scope underspecified. In a conversational agent, this can lead to accidental invocation during unrelated discussion of divination, classical texts, or cultural topics, reducing user control and increasing the chance of unintended data collection through the skill flow.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation states that the skill can connect to external LLM services for interpretation, but it does not warn users that their question content and possibly related configuration data will be transmitted to third-party endpoints. Because users may enter sensitive personal matters into a divination tool, the absence of disclosure meaningfully increases privacy and informed-consent risk.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill instructs users to paste API keys and endpoint information into the page without any warning about credential exposure, storage, or misuse risks. In a browser-based local HTML flow, secrets may be mishandled by the page logic, retained in local storage, exposed to other scripts, or accidentally sent to untrusted endpoints, making this more dangerous than a generic configuration omission.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The document declares `lang="zh-CN"`, and the prompt later hard-codes Chinese honorifics and stylistic constraints such as always calling the user "仙家" and responding in a classical Chinese tone. This is a language/locale constraint presented as mandatory behavior without user opt-in or a documented region-specific justification.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The page is not just a local divination UI: it collects an API key, allows the user to set an arbitrary base URL and model, and then sends prompts to that endpoint via fetch. This creates an unnecessary external data-exfiltration path and enables sensitive user input and credentials to be transmitted to untrusted destinations if the endpoint is changed.

External Transmission

Medium
Category
Data Exfiltration
Content
</div>
    <div class="cfg-row">
      <label>接口地址:</label>
      <input type="text" id="apiBase" value="https://api.openai.com/v1"/>
    </div>
    <div class="cfg-row">
      <label>模型:</label>
Confidence
88% confidence
Finding
The default external endpoint points to https://api.openai.com/v1, confirming that the skill performs outbound network transmission. In context, the risk is not the specific provider itself but that sensitive prompt contents and credentials are sent off-device from a divination UI that could otherwise operate locally.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The code transmits both the user-entered question and the API key to a configurable external endpoint, but the UI does not provide a clear, explicit warning that this data leaves the local skill. Because the endpoint is user-editable, users may unknowingly send secrets and personal content to an attacker-controlled service.

Context-Inappropriate Capability

Low
Confidence
92% confidence
Finding
The skill loads third-party font resources from Google Fonts, which causes the client to contact an external domain on page load. While not code execution, this leaks user metadata such as IP address, user agent, and timing to a third party without necessity for core divination functionality.

Static analysis

No suspicious patterns detected.