Back to skill

Security audit

YNote News

Security checks for vulnerabilities and agentic risk

Overview

This skill has a clear note-based news purpose, but it needs review because its fallback search can run mutable third-party code with inherited secrets and its YNote credential routing is under-validated.

Review before installing. This skill will read recent favorite YNote content, create topic summaries, send topic queries to external search providers, and can set up a recurring daily job. Avoid using it with sensitive notes unless you are comfortable with derived interests leaving the local environment, and prefer a version that pins the fallback search dependency, sanitizes subprocess environment variables, and validates MCP message endpoints before sending the YNote API key.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T03 · Remote Payload Retrieval and Execution

Error
Location
websearch-call.mjs:56
Finding
Unpinned Third-Party Package Is Downloaded and Executed with the Full Process Environment<![CDATA[ ## Vulnerability Details **File Location**: `websearch-call.mjs`, lines 56-63 **Vulnerability Type**: Mutable remote dependency execution and excessive environment inheritance **Risk Level**: High ### Vulnerable Code ```js const child = spawn('npx', ['open-websearch@latest'], { env: { ...process.env, MODE: 'stdio', DEFAULT_SEARCH_ENGINE: 'duckduckgo', ALLOWED_SEARCH_ENGINES: engines.join(','), }, stdio: ['pipe', 'pipe', 'inherit'], }); ``` ### Technical Analysis The fallback search implementation invokes `npx open-websearch@latest`. The mutable `latest` tag permits the effective code executed by the Skill to change after the Skill itself has been reviewed. There is no lockfile, exact version, integrity hash, or locally audited copy constraining which package release is executed. The spawned package also inherits the complete parent environment through `...process.env`. Depending on the runtime configuration, this environment may contain `YNOTE_API_KEY`, `PERPLEXITY_API_KEY`, `BRAVE_API_KEY`, or unrelated credentials available to the Agent process. The downloaded package therefore receives substantially more privilege than is necessary to perform an unauthenticated fallback web search. Although the package is declared as a search dependency, downloading and executing its latest release at runtime creates a remote code execution channel and a supply-chain trust dependency that exceeds minimum privilege. ### Attack Path 1. An attacker compromises the `open-websearch` package, its publishing account, or a package release referenced by the `latest` tag. 2. The attacker publishes a malicious release and causes it to become `latest`. 3. Perplexity and Brave search are unavailable or fail, causing the workflow to use the open-websearch fallback. 4. The Skill runs `npx open-websearch@latest`, which downloads and executes the attacker-controlled release. 5. The malicious package reads inherited environment variables, including avail ...[truncated 806 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `open-websearch@latest` with a reviewed, exact version. Do not use mutable tags in runtime execution paths. 2. Install the dependency during a controlled build or deployment phase rather than downloading it when the Skill runs. 3. Commit and enforce a lockfile, and verify package integrity using the registry-provided integrity digest or an independently maintained checksum. 4. Review the pinned package and its transitive dependencies before deployment. 5. Replace `...process.env` with a minimal allowlist containing only variables required by the subprocess, for example: ```js env: { PATH: process.env.PATH, HOME: process.env.HOME, MODE: 'stdio', DEFAULT_SEARCH_ENGINE: 'duckduckgo', ALLOWED_SEARCH_ENGINES: engines.join(','), } ``` 6. Explicitly exclude `YNOTE_API_KEY`, `PERPLEXITY_API_KEY`, `BRAVE_API_KEY`, and other credentials from the subprocess environment. 7. Where possible, run the fallback provider in a sandbox with restricted filesystem access, network destinations, and process-execution permissions. 8. Fail closed if the pinned and verified fallback component is unavailable instead of silently retrieving a new implementation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
mcp-call.sh:22
Finding
Unvalidated MCP Message Endpoint Can Redirect Authenticated Requests to an Attacker-Controlled Host<![CDATA[ ## Vulnerability Details **File Location**: `mcp-call.sh`, lines 22-82 **Vulnerability Type**: Origin-validation failure causing credential disclosure **Risk Level**: High ### Vulnerable Code ```bash SSE_URL="${YNOTE_MCP_URL:-https://open.mail.163.com/api/ynote/mcp/sse}" API_KEY="${YNOTE_API_KEY:?请设置 YNOTE_API_KEY 环境变量}" TIMEOUT="${YNOTE_MCP_TIMEOUT:-30}" # BASE_URL = scheme + host(从 SSE_URL 中提取,endpoint 是绝对路径) BASE_URL=$(echo "$SSE_URL" | sed 's|^\(https\{0,1\}://[^/]*\).*|\1|') # ... ENDPOINT="" for _ in $(seq 1 100); do ENDPOINT=$(grep '^data:' "$SSE_OUT" 2>/dev/null | head -1 | sed 's/^data://' || true) [ -n "$ENDPOINT" ] && break sleep 0.1 done if [ -z "$ENDPOINT" ]; then echo '{"error":"SSE 连接超时,未获取到 endpoint"}' >&2 exit 1 fi MESSAGE_URL="${BASE_URL}${ENDPOINT}" # ─── Step 2: MCP 握手(initialize + initialized)─── curl -sf -X POST "$MESSAGE_URL" \ -H "Content-Type: application/json" \ -H "x-api-key: $API_KEY" \ --max-time "$TIMEOUT" \ -d "$(jq -nc '{jsonrpc:"2.0",id:1,method:"initialize",params:{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"ynote-clip",version:"1.0.0"}}}')" \ >/dev/null 2>&1 sleep 0.5 curl -sf -X POST "$MESSAGE_URL" \ -H "Content-Type: application/json" \ -H "x-api-key: $API_KEY" \ --max-time "$TIMEOUT" \ -d '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}' \ >/dev/null 2>&1 # ─── Step 3: 调用目标 Tool ─── curl -sf -X POST "$MESSAGE_URL" \ -H "Content-Type: application/json" \ -H "x-api-key: $API_KEY" \ --max-time "$TIMEOUT" \ -d "$(jq -nc --arg name "$TOOL_NAME" --argjson args "$TOOL_ARGS" \ '{jsonrpc:"2.0",id:2,method:"tools/call",params:{name:$name,arguments:$args}}')" \ >/dev/null 2>&1 ``` ### Technical Analysis The MCP server supplies an endpoint through the SSE stream. The script concatenates this untrusted value directly with a manually extracted base URL and then sends the YNote API key to th ...[truncated 2284 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the returned endpoint using a standards-compliant URL parser rather than string concatenation. 2. Require the endpoint returned by SSE to be a relative path beginning with `/`. 3. Reject endpoints containing a scheme, hostname, user-information component, backslashes, control characters, or protocol-relative prefix such as `//`. 4. Verify that the resolved message URL has exactly the same HTTPS origin—scheme, hostname, and effective port—as the configured SSE URL. 5. Reject non-HTTPS `YNOTE_MCP_URL` values except for an explicitly enabled local-development mode. 6. Before sending credentials, log or validate the normalized destination without logging the API key. 7. Consider configuring the MCP message path locally instead of trusting a server-provided destination if the protocol and deployment permit it. 8. Apply server-side least privilege to `YNOTE_API_KEY`, rotate any key that may have been exposed, and restrict each key to only the MCP tools required by this Skill. 9. Add tests covering hostile endpoint values, including: ```text @attacker.example/path //attacker.example/path https://attacker.example/path \attacker.example\path ``` The request must be aborted whenever the normalized destination origin differs from the configured SSE origin. ]]>
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 (26)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill presents itself as a note-based news briefing tool but also documents undeclared external search behavior, including use of a Perplexity search script and fallback web search providers. Description-behavior mismatches are dangerous because users may consent to local note analysis without realizing their derived interests and queries are sent to third-party services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The skill presents itself as a note-based news briefing tool but also documents undeclared external search behavior, including use of a Perplexity search script and fallback web search providers. Description-behavior mismatches are dangerous because users may consent to local note analysis without realizing their derived interests and queries are sent to third-party services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill presents itself as a note-based news briefing tool but also documents undeclared external search behavior, including use of a Perplexity search script and fallback web search providers. Description-behavior mismatches are dangerous because users may consent to local note analysis without realizing their derived interests and queries are sent to third-party services.

Chaining Abuse

High
Category
Tool Misuse
Content
BASE_URL=$(echo "$SSE_URL" | sed 's|^\(https\{0,1\}://[^/]*\).*|\1|')

TMPDIR_MCP=$(mktemp -d)
trap 'kill "$SSE_PID" 2>/dev/null; wait "$SSE_PID" 2>/dev/null; rm -rf "$TMPDIR_MCP"' EXIT

SSE_OUT="$TMPDIR_MCP/sse.out"
touch "$SSE_OUT"
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Credential Access

High
Category
Privilege Escalation
Content
process.stderr.write(
    '错误:未设置 PERPLEXITY_API_KEY\n' +
    '配置方式:\n' +
    '  1) 在 ~/.openclaw/openclaw.json 的 skills.entries["ynote-news"].env 中添加 "PERPLEXITY_API_KEY": "pplx-..."\n' +
    '  2) 或在 shell 中 export PERPLEXITY_API_KEY="pplx-..."(Key 在 https://www.perplexity.ai/settings/api 获取)\n'
  );
  process.exit(1);
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The implementation does not match the declared skill purpose of analyzing Youdao notes and pushing related news; instead it is a generic web-search wrapper. This capability mismatch is security-relevant because it obscures what data leaves the system and can hide undeclared external communications, reducing user and reviewer ability to assess privacy and operational risk.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill requires shell, network, and environment-variable access but does not declare an explicit tool/permission scope. That makes the effective capability boundary unclear to reviewers and runtime policy, increasing the chance of overbroad execution or abuse if the skill is triggered unexpectedly.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill does not clearly warn that it reads and analyzes recently favorited note content, which may contain sensitive personal or business information. In this context, the risk is elevated because extracted topics are then used to query external search providers, potentially disclosing user interests derived from private notes.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger phrases are broad everyday language such as '最近关注' or '每日简报', which can cause accidental activation. Because this skill accesses note content, performs network searches, and may schedule recurring jobs, unintended triggering can lead to privacy-impacting actions without clear user intent.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The documentation instructs use of an embedded default Perplexity API key for external search. Bundling or relying on a shared hidden key is risky because it obscures credential provenance, may violate least-privilege expectations, and can route user-derived queries through an account the user does not control or audit.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script sends the sensitive YNOTE_API_KEY value as an x-api-key header during network requests, but provides no explicit warning to the user that credentials will be transmitted to a remote service. While network access is central to the script's purpose, the handling of a credential is safety-relevant and this file lacks a visible disclosure beyond the mechanical usage line.

External Transmission

Medium
Category
Data Exfiltration
Content
# ─── Step 2: MCP 握手(initialize + initialized)───

curl -sf -X POST "$MESSAGE_URL" \
    -H "Content-Type: application/json" \
    -H "x-api-key: $API_KEY" \
    --max-time "$TIMEOUT" \
Confidence
88% confidence
Finding
The script posts authenticated requests to a dynamically constructed MESSAGE_URL derived from SSE_URL/ENDPOINT without validating that the destination remains within a trusted HTTPS origin. If an attacker can influence YNOTE_MCP_URL or the SSE-provided endpoint, the API key and tool-call data could be sent to an attacker-controlled service, causing credential leakage and unauthorized external data transmission.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
The skill's stated purpose is generating news pushes based on note topics, and this helper is documented as a Perplexity search caller. Instead of only using an explicitly provided API key, it inspects process environment variables and parses the user's local OpenClaw config file to extract credentials, which is a broader credential-access capability not justified by the narrow search-call purpose described in the file and manifest.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This script automatically loads an API credential from environment or local config and sends user-provided query content to a third-party service. In a skill context, that creates a data-sharing risk because note-derived or user-entered content may be transmitted externally without any consent check or user-visible warning in the execution path.

External Transmission

Medium
Category
Data Exfiltration
Content
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);

try {
  const resp = await fetch('https://api.perplexity.ai/search', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
Confidence
92% confidence
Finding
The hardcoded external endpoint confirms that data is transmitted to a third-party API. While this is functionally necessary for the skill, it is still security-relevant because the skill context involves personalized news generation from note content, increasing privacy sensitivity of outbound queries.

External Transmission

Medium
Category
Data Exfiltration
Content
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);

try {
  const resp = await fetch('https://api.perplexity.ai/search', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
Confidence
92% confidence
Finding
The hardcoded external endpoint confirms that data is transmitted to a third-party API. While this is functionally necessary for the skill, it is still security-relevant because the skill context involves personalized news generation from note content, increasing privacy sensitivity of outbound queries.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
The script executes `npx open-websearch@latest`, which fetches and runs the newest package version at runtime without pinning or integrity control. This creates a supply-chain risk: a compromised upstream release or dependency can execute arbitrary code in the skill environment, and the danger is amplified because the subprocess inherits the parent environment.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The code dynamically installs and executes an external package through `npx open-websearch@latest`, giving the skill undeclared code-execution capability beyond its stated note-based news function. Because the package is fetched at runtime, any compromise of the package or its dependencies can immediately become remote code execution in the host context.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The subprocess is launched with `...process.env`, exposing all parent environment variables to a dynamically fetched external package. If secrets such as API keys, tokens, or internal configuration are present, a malicious or compromised package can read and exfiltrate them, making the combination of inherited environment plus runtime-installed code particularly dangerous.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The subprocess is launched with `...process.env`, exposing all parent environment variables to a dynamically fetched external package. If secrets such as API keys, tokens, or internal configuration are present, a malicious or compromised package can read and exfiltrate them, making the combination of inherited environment plus runtime-installed code particularly dangerous.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The scheduled execution flow does not clearly warn users that enabling it will repeatedly access note data and send notifications automatically. Recurrent background processing raises the privacy impact because sensitive note-derived topics may be processed on an ongoing basis after a one-time setup.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The file's human-readable instructions, comments, and error/help text are presented in Chinese only, with no option for alternative language or indication that the skill is intentionally region-specific. This can violate language/locale policy when a skill imposes a single language on users without opt-in or justification.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
The natural-language instructions, parameter descriptions, and error guidance in the file comments are presented exclusively in Chinese. That creates a language/locale constraint for users or maintainers without offering an alternative language or explicit opt-in.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The script unconditionally defaults LANG and LC_ALL to en_US.UTF-8 when those variables are unset. This is a natural-language/locale policy concern because it imposes a specific locale choice rather than offering user selection or clearly documenting a required regional constraint.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
Comments and usage instructions in the file force a specific language for human-readable guidance, which can violate language/locale policy when no user choice is provided. There is no indication that the language constraint is optional or justified by a region-specific purpose.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
websearch-call.mjs:56

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
perplexity-search-call.mjs:88

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
perplexity-search-call.mjs:110