Back to skill

Security audit

zion-xhs-catch-skill

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real Xiaohongshu scraping and reporting tool, but it combines logged-in browser automation, unverified remote installer execution, plaintext credential storage, external uploads, and silent sibling-project credential reuse.

Review before installing. Use only an isolated browser profile and non-critical Xiaohongshu account, avoid running the remote installer pipeline unless you independently trust and verify it, do not sync sensitive or private scraped data, and remove or fix the sibling credential fallback and plaintext secret storage before using Howtone/Zion sync.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/webbridge-crawl.ts:74
Finding

Automatic Execution of an Unverified Remote Installer

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate-report.ts:225
Finding

Stored Cross-Site Scripting in Generated HTML Reports

Content
View full analysis
const allData = ${jsonData}; function renderCards(data) { const container = document.getElementById('cards'); if (data.length === 0) { container.innerHTML = '
没有找到匹配的内容
'; return; } container.innerHTML = data.map((item, idx) => `
${item.images && item.images.length ? `
${item.images.slice(0, 3).map(img => ``).join('')}
` : ''}
#${item.keyword || ''}
${item.title || '无标题'}
${item.content || ''}
${item.author_name || '匿名'}
${item.comments && item.comments.length ? `
💬 查看 ${item.comments.length} 条评论
${item.comments.map(c => `
${c.author}
${c.content}
`).join('')}
` : ''}
`).join(''); } ``` The pain-point view repeats the unsafe rend ...[truncated 2074 chars]
Remediation
View remediation
`, `&`, Unicode line separators, and script-closing sequences, or place encoded JSON in a non-executable data element. 5. Consider loading the JSON separately rather than interpolating it into an executable script. 6. Add a restrictive Content Security Policy that blocks inline scripts and limits outbound connections and image sources. 7. Add regression tests using payloads containing HTML tags, event handlers, quotes, template-literal syntax, and ``. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sync.ts:37
Finding

Arbitrary URL Fetching Followed by Public Re-Upload

Content
View full analysis
{ try { const resp = await fetch(url); if (!resp.ok) throw new Error(`HTTP ${resp.status}`); const buffer = Buffer.from(await resp.arrayBuffer()); const md5 = crypto.createHash('md5').update(buffer).digest('base64'); let suffix = 'JPG'; if (url.toLowerCase().endsWith('.png')) suffix = 'PNG'; else if (url.toLowerCase().endsWith('.webp')) suffix = 'WEBP'; else if (url.toLowerCase().endsWith('.gif')) suffix = 'GIF'; const gql = { query: ` mutation GetImageUploadUrl($md5: String!, $suffix: MediaFormat!) { imagePresignedUrl(imgMd5Base64: $md5, imageSuffix: $suffix, acl: PUBLIC_READ) { imageId uploadUrl uploadHeaders } } `, variables: { md5, suffix }, }; const res = await fetch(config.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${config.token}`, }, body: JSON.stringify(gql), }); const json = await res.json(); if (json.errors) throw new Error(JSON.stringify(json.errors)); const { imageId, uploadUrl, uploadHeaders } = json.data.imagePresignedUrl; const headers: Record = { 'Content-Type': resp.headers.get('content-type') || 'image/jpeg', }; if (uploadHeaders) { if (Array.isArray(uploadHeaders)) { uploadHeaders.forEach((h: any) => { headers[h.key] = h.value; }); } else { Object.entries(uploadHeaders).forEach(([k, v]) => { headers[k] = v as string; }); } } const putRes = await fetch( ...[truncated 2505 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/sync.ts:141
Finding

Silent Reuse of Administrative Credentials from a Sibling Project

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/zion-login.ts:57
Finding

Browser Cookies and Administrative Tokens Stored in Plaintext

Content
View full analysis
a.startsWith('--token='))?.split('=')[1]; ``` ### Technical Analysis `login.ts` writes the complete Playwright cookie set to `cookies.json`, potentially including reusable session cookies. `zion-login.ts` writes an administrative bearer token to a plaintext YAML file. Neither write operation specifies restrictive file permissions. On systems with permissive process umasks, these files may be readable by other local users. They may also be captured by backups, development tools, support bundles, or accidental version-control commits. Passing the bearer token through `--token=...` can expose it in shell history and, depending on the operating system, process listings. Persisting Xiaohongshu cookies is also unnecessary for the WebBridge crawler shown in this project because that crawler controls an already logged-in real browser and does not read `cookies.json`. ### Attack Path 1. The user runs `login.ts` or `zion-login.ts`. 2. Reusable cookies or an administrative token are written to pl ...[truncated 731 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (60)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill description omits that it accepts sync tokens, parses JWTs, creates local credential files, and configures external authentication state. That mismatch is security-relevant because token and identity handling requires a much higher trust level than ordinary content collection and reporting.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill description omits that it accepts sync tokens, parses JWTs, creates local credential files, and configures external authentication state. That mismatch is security-relevant because token and identity handling requires a much higher trust level than ordinary content collection and reporting.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill description omits that it accepts sync tokens, parses JWTs, creates local credential files, and configures external authentication state. That mismatch is security-relevant because token and identity handling requires a much higher trust level than ordinary content collection and reporting.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

The documentation tells users to fetch and immediately execute a remote shell script via curl ... | bash. This is a classic arbitrary code execution and supply-chain risk: if the remote server, CDN, DNS path, or script content is compromised, the operator will run attacker-controlled code on their machine with their user privileges.

Content

Scanner excerpt · SKILL.md (reported line 35)May include surrounding context.

  • Mac / Linux 用户: 直接在终端运行以下命令:
    bash
    curl -fsSL https://cdn.kimi.com/webbridge/install.sh | bash
    
  • Windows 用户: 在 PowerShell 中运行以下命令:

Chaining Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

The | bash pattern explicitly chains network retrieval into immediate execution, removing any review or integrity-verification step. In a skill that already requests browser control and authenticated sessions, this materially heightens the chance of full host compromise and subsequent theft of cookies, tokens, and local data.

Content

Scanner excerpt · SKILL.md (reported line 35)May include surrounding context.

  • Mac / Linux 用户: 直接在终端运行以下命令:
    bash
    curl -fsSL https://cdn.kimi.com/webbridge/install.sh | bash
    
  • Windows 用户: 在 PowerShell 中运行以下命令:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 80)May include surrounding context.

md
| `webbridge-crawl.ts` | 通过 WebBridge 控制用户真实浏览器采集 |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 82)May include surrounding context.

md
| `zion-login.ts` | 保存「好痛 Howtone」项目同步 Token |

Ssd 3

High
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill instructs users to save a synchronization token and upload collected data, including images, to an external platform. This is high risk because it combines credential handling with bulk exfiltration of harvested content to a third party, and the documentation does not clearly define trust, storage, retention, or access controls.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 83)May include surrounding context.

md
| `sync.ts` | 将采集数据同步到「好痛 Howtone」项目(含图片上传) |

Ssd 3

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The optional Howtone workflow asks the user to provide a sync token and send output files for external analysis, creating a clear channel for credential use and outbound data transfer. In the context of scraped, possibly account-derived content, this materially increases data leakage, compliance, and unauthorized-sharing risk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The code probes a predictable local path for .zion/credentials.yaml, indicating credential access behavior. In an agent skill, accessing stored credentials for a separate service materially increases risk because it can leverage existing admin tokens to perform authenticated actions beyond the user's expectation for a note-collection tool.

Content

Scanner excerpt · scripts/sync.ts (reported line 141)May include surrounding context.

ts
}

function loadConfig(): ZionConfig {
  const zionCredPath = path.resolve(process.cwd(), '.zion', 'credentials.yaml');
  const siblingZionCredPath = path.resolve(process.cwd(), '..', 'pain-catcher', '.zion', 'credentials.yaml');
  
  let credPath = fs.existsSync(zionCredPath) ? zionCredPath : (fs.existsSync(siblingZionCredPath) ? siblingZionCredPath : null);

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

The code also searches a sibling project directory (../pain-catcher/.zion/credentials.yaml) for credentials, broadening secret discovery beyond the current workspace. This increases the likelihood of unauthorized credential use and resembles lateral secret harvesting from adjacent projects.

Content

Scanner excerpt · scripts/sync.ts (reported line 142)May include surrounding context.

ts
function loadConfig(): ZionConfig {
  const zionCredPath = path.resolve(process.cwd(), '.zion', 'credentials.yaml');
  const siblingZionCredPath = path.resolve(process.cwd(), '..', 'pain-catcher', '.zion', 'credentials.yaml');
  
  let credPath = fs.existsSync(zionCredPath) ? zionCredPath : (fs.existsSync(siblingZionCredPath) ? siblingZionCredPath : null);

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

Although this line is only an error message, it confirms to users and reviewers that the script expects and targets .zion/credentials.yaml for credential access. That reinforces the credential-access behavior but is not independently as severe as the actual file reads on lines 141-142.

Content

Scanner excerpt · scripts/sync.ts (reported line 161)May include surrounding context.

ts
}
  }

  throw new Error('未找到有效 Zion 配置,请检查 .zion/credentials.yaml');
}

function buildInsertMutation(tableName: string, note: XHSNote, imageIds: string[], userId?: string): { query: string; variables: Record<string, any> } {

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The crawler performs remote installation automatically and without prior user approval, violating the principle of least surprise and removing an important safety checkpoint before executing privileged code. In a skill that already interacts with a real logged-in browser, silent installation substantially increases the chance of unwanted persistence or host compromise.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Piping a remote script directly into bash/PowerShell executes unverified code from the network with the user's privileges, enabling full system compromise if the CDN, DNS, TLS path, or upstream publisher is compromised. This is especially severe here because the skill also expects access to a logged-in browser session, so compromise could expose local data, browser context, and authenticated accounts.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
99% confidence
Finding

Fetching an installer script over the network and piping it directly to bash is a classic remote code execution pattern with no integrity validation. Within this skill's context, it is especially dangerous because the resulting installed component can control the user's browser and access authenticated browsing activity.

Content

Scanner excerpt · scripts/webbridge-crawl.ts (reported line 81)May include surrounding context.

ts
if (isWin) {
        execSync('powershell -Command "irm https://cdn.kimi.com/webbridge/install.ps1 | iex"', { stdio: 'inherit' });
      } else {
        execSync('curl -fsSL https://cdn.kimi.com/webbridge/install.sh | bash', { stdio: 'inherit' });
      }
      console.log('✅ Kimi WebBridge 安装成功!');
    } catch (err) {

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/webbridge-crawl.ts (reported line 89)May include surrounding context.

ts
if (isWin) {
        console.error('   irm https://cdn.kimi.com/webbridge/install.ps1 | iex');
      } else {
        console.error('   curl -fsSL https://cdn.kimi.com/webbridge/install.sh | bash');
      }
      return false;
    }

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The script explicitly instructs the user to provide a synchronization token and persists it as credential material, which is direct credential handling. In the context of a scraping skill, this is more sensitive because the token is unrelated to basic collection and may grant access to an external analysis platform if stolen.

Content

Scanner excerpt · scripts/zion-login.ts (reported line 3)May include surrounding context.

ts
/**
 * Zion 凭证保存脚本
 * 直接接收用户提供的「好痛 Howtone」同步 Token,并保存到 .zion/credentials.yaml
 * 
 * 用法:
 *   npx ts-node zion-login.ts --token="你的同步Token"

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

The code defines a fixed path for credentials.yaml under the current working directory and later stores the token there in plaintext-like form, creating a stable target for theft. A predictable credential file in a workspace increases the chance of accidental exposure through local compromise, repository inclusion, shared directories, or support bundles.

Content

Scanner excerpt · scripts/zion-login.ts (reported line 13)May include surrounding context.

ts
import * as path from 'path';

const PROJECT_EX_ID = 'rmLyJ0ZJXK8';
const CRED_PATH = path.resolve(process.cwd(), '.zion', 'credentials.yaml');

function decodeJwt(token: string): any {
  try {

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill declares powerful capabilities such as shell, network, and environment access but does not restrict or document tool scope. In a skill that automates browser actions, installs software, stores tokens, and uploads data externally, missing explicit permission boundaries increases the chance of overreach, unintended execution, or abuse by downstream prompts.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad enough to activate during ordinary discussion about Xiaohongshu, research, or content topics. Over-broad activation is risky for a skill with shell, network, login, scraping, and upload behaviors because it can cause the agent to enter a sensitive workflow without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The description does not prominently disclose the privacy, account, and third-party transmission implications of scraping logged-in content and synchronizing outputs to an external platform. In this context, omission is dangerous because the workflow handles user/account-derived data and may expose it outside the original platform.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill directly instructs collection of account-derived browsing data and comments, then offers synchronization to a third-party analysis platform. This is sensitive because logged-in browsing context and user-generated content may include personal data, and the transfer broadens exposure beyond the original source platform.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instructions require the operator to remain logged into a real platform account while automation drives the browser to collect data. That raises both account-security and privacy risk because session-backed access is more sensitive than public browsing, and automation against a live session can expose private state, cookies, and platform-enforcement consequences.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding

Using npx ts-node without pinning exact package versions makes execution dependent on whatever version resolves at runtime. That creates supply-chain and reproducibility risk, especially in a skill that handles authenticated sessions and may access local files or external services.

Content

No source excerpt is available for this finding.