Back to skill

Security audit

YoudaoNote Clip

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches webpage clipping, but it has broad network and credential paths that could upload sensitive or internal content without enough guardrails.

Review before installing. Only use this with trusted pages and trusted Youdao MCP configuration, avoid custom MCP URLs unless they are known HTTPS endpoints, and expect clipped page text, image data, source URLs, and possibly AI-chat transcripts to be uploaded. Do not use it for sensitive internal pages until image fetching and endpoint validation are tightened.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
clip-note.mjs:396
Finding

Unrestricted Image Fetching Enables Server-Side Request Forgery and Data Exfiltration

Content
View full analysis
img.getAttribute('src')) .filter(src => src && !src.startsWith('data:')) .map(src => { try { return new URL(src, document.baseURI).href; } catch(e) { return null; } }) .filter(Boolean); return { title: r.title || document.title, content: r.content, source: r.source, imageUrls: [...new Set(imageUrls)] }; ``` The collected URL is then fetched directly with automatic redirect following: ```js async function downloadImage(url, referer, destPath) { try { return await fetchImageViaFetch(url, referer, 10_000, destPath); } catch (e) { // Trigger DNS fallback on timeout. if (e.name === 'AbortError' || (e.message && e.message.includes('timeout'))) { debug(`DNS fallback triggered — url: ${url}, reason: ${e.message}`); return await fetchImageWithDnsFallback(url, referer, destPath); } throw e; } } async function fetchImageViaFetch(url, referer, timeoutMs, destPath) { const res = await fetch(url, { headers: { 'Referer': referer, 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36', }, signal: AbortSignal.timeout(timeoutMs), redirect: 'follow', }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const contentType = res.headers.get('content-type')?.split(';')[0]?.trim() || ''; ``` The fallback performs public DNS resolution and connects directly to the resulting IP, but do ...[truncated 5128 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
clip-note.mjs:224
Finding

Configurable MCP Endpoint Can Receive the Youdao API Key over an Untrusted or Plaintext Connection

Content
View full analysis
{ const timer = setTimeout(() => { this.close(); reject(new Error(`SSE connection timeout (${CONNECT_TIMEOUT_MS}ms)`)); }, CONNECT_TIMEOUT_MS); const proto = this.#sseUrl.protocol === 'https:' ? https : http; const parser = new SseParser((event) => { if (event.type === 'endpoint') { this.#messageUrl = new URL(event.data, this.#sseUrl); this.#connected = true; clearTimeout(timer); resolve(); } else if (event.type === 'message') { this.#handleMessage(event.data); } }); this.#request = proto.request({ hostname: this.#sseUrl.hostname, port: this.#sseUrl.port || ...[truncated 3750 chars]
Remediation
View remediation
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 Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (35)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的核心能力是“网页剪藏到有道云笔记”,通常应包含网页内容获取、整理,并提交到有道云笔记的行为。但该代码片段仅实现三阶段流水线中的图片压缩与编码环节,处理的是本地图片文件和 manifest 元数据,没有任何与网页保存或有道云笔记 API/服务交互相关的逻辑。虽然这可能是更大剪藏流程中的辅助模块,但就该代码块实际行为而言,其主要功能与声明用途不一致,应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding

声明的核心目的,是把网页剪藏到有道云笔记;但提供的代码片段实际只是在当前页面环境中注入解析器、等待其可用,然后抓取页面内容与图片地址并返回结构化结果。它没有展示任何与有道云笔记相关的 API 调用、认证、存储、同步或提交动作。因此,这段代码的主要行为更接近“网页内容解析/提取”,而不是“保存到有道云笔记”。脚本注入本身可视为实现细节,但由于最终缺失声明中的关键落地行为(保存到有道云笔记),应判定描述与代码行为不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

声明的核心目的,是把网页剪藏到有道云笔记;但提供的代码片段只调用页面解析器收集内容,并整理图片地址后返回结构化结果。它没有体现登录、调用有道云笔记接口、写入笔记、存储或网络传输等与“保存到有道云笔记”直接相关的行为。因此,该代码与声明用途相比,主功能存在实质性缺失。虽然页面解析可能是剪藏流程的一个支持步骤,但就这段代码本身而言,更准确的描述应是“解析网页并提取内容与图片链接”,而不是“保存到有道云笔记”。

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 117)May include surrounding context.

md
变量**:核心模块 clip-note.mjs 不直接读取 `process.env`,由 `clip-note.sh` 从环境变量读取后通过命令行参数传入。`twitter-apify.mjs` 从 `process.env` 读取 `APIFY_API_TOKEN`(可选,仅 Twitter/X 路径使用)和 `Y

Ssd 3

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The site configuration explicitly includes multiple AI chat domains and routes them through specialized getContent handlers intended to harvest complete chat sessions. In the context of a skill described as webpage clipping, this broadens collection into high-sensitivity conversational data and increases the chance of exporting confidential prompts and generated outputs unintentionally.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The formatter serializes every captured question and answer, along with original link and timestamp, into saved output. Persisting complete conversational transcripts amplifies privacy and confidentiality impact because it creates a durable record of potentially sensitive exchanges that can later be synced, shared, or exposed.

Content

No source excerpt is available for this finding.

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · static/marked.mjs (reported line 13)May include surrounding context.

js
* The code in this file is generated from files in ./src/
 */

function M(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var T=M();function H(u){T=u}var _={exec:()=>null};function k(u,e=""){let t=typeof u=="string"?u:u.source,n={replace:(r,i)=>{let s=typeof i=="string"?i:i.source;return s=s.replace(m.caret,"$1"),t=t.replace(r,s),n},getRegex:()=>new RegExp(t,e)};return n}var Re=(()=>{try{return!!new RegExp("(?<=1)(?<!1)")}catch{return!1}})(),m={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notS
...[truncated 27 chars]

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file’s behavior materially differs from the stated skill purpose: instead of clipping arbitrary webpages to Youdao Note, it sends user-supplied Twitter/X URLs and related content to a third-party service (Apify) for scraping and transformation. This creates a trust-boundary violation and hidden data flow, because users invoking a note-clipping skill would not reasonably expect external processing by Apify or Twitter-specific collection logic.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill invokes shell commands, network access, MCP calls, browser tooling, and reads environment variables, but it does not declare an explicit tool/permission scope. That creates unnecessary ambient authority: if the runtime grants broad defaults, the skill can access more capabilities than users or reviewers expect, increasing blast radius if the skill is modified or misused.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Broad trigger phrases like '保存网页' and '收藏网页' are common conversational expressions and may cause the skill to activate when the user did not intend to invoke a tool with browser, shell, network, and note-storage capabilities. Unintended activation can lead to accidental browsing, content capture, or external storage of sensitive pages.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
77% confidence
Finding

The security documentation says the injected browser script does not send network requests, but the documented overall flow includes a web_fetch fallback. Even if the fallback is separate from the injected script, the wording can mislead reviewers and users about when network retrieval occurs and what data may leave the local browser context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill downloads remote images and stores them on disk and in a cache/temp area during normal operation without a clear runtime warning, consent prompt, or prominent disclosure in code paths. In this context, clipped pages may contain sensitive or private image URLs, so silent local staging increases privacy and data-handling risk, especially on shared systems.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The DNS fallback forces resolution through a public resolver (8.8.8.8) and then connects directly by IP, bypassing the system resolver and potentially enterprise DNS controls, split-horizon DNS, monitoring, or policy enforcement. In a clipping skill, this is more dangerous because it silently broadens network reach and can send requests to destinations the host’s normal network configuration would have blocked or resolved differently.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes a narrowly scoped web-clipping skill triggered by phrases like '剪藏网页' and '保存网页'. However, the CLI supports a separate '--create-note' mode with arbitrary '--content' and optional '--folder-id', and later calls the backend 'createNote' tool directly, which goes beyond clipping an existing web page and enables general note authoring.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

In create-note mode, the skill reads an API key and sends arbitrary note content to a remote service without a clear user-facing warning. This is especially sensitive because the mode is generic note creation rather than just clipping a webpage, so it can transmit any user-supplied content, increasing the chance of accidental leakage of sensitive data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This path uploads note title/content, source URLs, and base64-encoded image data to a remote MCP service, but there is no visible runtime warning or consent step in the execution flow. Because webpage clips can contain personal, proprietary, or confidential content, undisclosed transmission to a remote endpoint creates a meaningful privacy and data-exfiltration risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

When debug mode is enabled, the script writes clipping metadata derived from the user-supplied data file into a persistent directory on disk. Even though it avoids storing full page content, the logged title, source URL, debug key, and image count/content length can still reveal sensitive browsing activity and document metadata, and this happens without any visible user warning or retention control in the script.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file's natural-language interface and operational comments are presented entirely in Chinese, including the usage message and parameter descriptions. Under the stated policy, forcing a specific language without opt-in is a locale/language policy violation unless the constraint is documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes a skill for clipping webpages to Youdao Notes, but this file explicitly moves image-processing logic into a Bash script so the JavaScript layer no longer imports child_process. Spawning OS-level tools such as sips, convert, identify, stat, jq, and base64 is a broader capability than the user-facing purpose requires and is specifically documented as a compliance workaround rather than a clipping requirement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script rewrites the input manifest in place using redirected output, which is a file write affecting user data. Although comments describe the output behavior for developers, there is no user-facing confirmation, prompt, or runtime notice before modifying the provided manifest file.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code contains dedicated extractors for multiple AI chat sites and walks full message lists to collect both prompts and replies. That exceeds a narrow webpage-clipping function and creates privacy-sensitive data collection risk because users may clip pages while unknowingly including full conversation history from third-party AI services.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

These routines enumerate chat containers on DeepSeek, Yuanbao, Tongyi, Kimi, Doubao, and Yiyan, then preserve user questions and model answers as HTML/text. AI chat logs often contain secrets, internal data, credentials, or sensitive business context, so silent collection and export of conversation history materially increases data-exfiltration and privacy risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code gathers content from third-party pages and chat services without any visible notice, prompt, or gating in this file. Lack of disclosure is dangerous because it prevents informed consent and makes privacy-invasive collection harder for users to detect, especially on sites holding personal or proprietary content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file’s natural-language comments and thrown error message are written exclusively in Chinese, which indicates a fixed language choice with no user opt-in or documented justification. The policy explicitly calls for flagging language or locale constraints when the skill forces a specific language without offering choice.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This code transmits user-provided Twitter/X URLs and an Apify API token to an external service, which is a real data egress event. In the context of a clipping skill, sending content to an undisclosed third-party processor increases privacy, compliance, and secret-handling risk, especially because the transfer is central to operation rather than incidental telemetry.

Content

Scanner excerpt · twitter-apify.mjs (reported line 192)May include surrounding context.

js
maxItems: 1,
  };

  const url = `https://api.apify.com/v2/acts/${ACTOR_ID}/runs?token=${token}`;

  debug(`🔍 启动 Apify Actor — URL: ${tweetUrl}`);

Static analysis

No suspicious patterns detected.