Back to skill

Security audit

Yinxiang Skill 1.0.4

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Yinxiang/Evernote integration that uses the user's token to manage notes, with some credential-handling and input-escaping weaknesses to be aware of.

Install only if you trust this skill with your Yinxiang notes. It can read note details and create or modify notes, notebooks, and tags using your token. Prefer a short-lived or revocable token, avoid pasting long-lived secrets where logs are retained, and rotate the token if it may have been exposed.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/get-note-detail.sh:4
Finding
Unsafe JSON Construction in the Bash Note-Detail Request<![CDATA[ ## Vulnerability Details **File Location**: `scripts/get-note-detail.sh:4-14` **Vulnerability Type**: JSON injection through unescaped user-controlled input **Risk Level**: Medium ### Vulnerable Code ```bash source "$(dirname "$0")/_common.sh" GUID="$1" if [ -z "$GUID" ]; then echo "用法: $0 <笔记GUID>" exit 1 fi curl -s -X POST \ "https://app.yinxiang.com/third/ai-chat-note/grpc-api/search/getNoteDetail" \ -H "Content-Type: application/json" \ -H "auth: $TOKEN" \ -d "{\"guid\":\"$GUID\",\"source\":\"skill\",\"resultSpec\":{\"includeContent\":true,\"includeResources\":false,\"includeTags\":true,\"includeResourceContent\":false}}" ``` ### Technical Analysis The script inserts the first command-line argument directly into a JSON string without applying JSON escaping or validating the expected GUID format. Shell quoting prevents ordinary shell command substitution inside the already-expanded variable, so this is not a local shell-command injection vulnerability. However, characters such as quotes and backslashes can terminate or alter the JSON string. For example, a crafted value could inject additional JSON properties or create duplicate properties. Whether an altered request is accepted, and which duplicate value takes precedence, depends on the remote service's JSON parser and request validation. The project already uses `python3` with `json.dumps` in other Bash scripts, demonstrating that safe serialization is available but is not used here. ### Attack Path 1. An attacker persuades a user or agent to process a crafted value as a note GUID. 2. The agent invokes `get-note-detail.sh` with the crafted value as its first argument. 3. The script places that value directly inside the JSON request body. 4. Quotes or JSON delimiters in the value alter or invalidate the request structure. 5. The authenticated request is sent to the Yinxiang note-detail endpoint using the victim's token. 6. If the server accepts the modified structure, unintend ...[truncated 640 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Construct the request as a native object and serialize it with a JSON encoder: ```bash BODY=$(python3 - "$GUID" <<'PY' import json import sys body = { "guid": sys.argv[1], "source": "skill", "resultSpec": { "includeContent": True, "includeResources": False, "includeTags": True, "includeResourceContent": False, }, } print(json.dumps(body, ensure_ascii=False)) PY ) curl -s -X POST \ "https://app.yinxiang.com/third/ai-chat-note/grpc-api/search/getNoteDetail" \ -H "Content-Type: application/json" \ -H "auth: $TOKEN" \ -d "$BODY" ``` Additionally: - Validate that the value matches the documented GUID format before sending it. - Reject control characters and unexpected input lengths. - Add regression tests containing quotes, backslashes, newlines, and JSON delimiters. - Apply the same serialization pattern consistently to every request body. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/get-note-detail.ps1:1
Finding
Unsafe JSON Construction in the PowerShell Note-Detail Request<![CDATA[ ## Vulnerability Details **File Location**: `scripts/get-note-detail.ps1:1-8` **Vulnerability Type**: JSON injection through unescaped user-controlled input **Risk Level**: Medium ### Vulnerable Code ```powershell param([Parameter(Mandatory)][string]$Guid) . "$PSScriptRoot\_common.ps1" $body = "{`"guid`":`"$Guid`",`"source`":`"skill`",`"resultSpec`":{`"includeContent`":true,`"includeResources`":false,`"includeTags`":true,`"includeResourceContent`":false}}" Invoke-YinxiangPost ` -Uri "https://app.yinxiang.com/third/ai-chat-note/grpc-api/search/getNoteDetail" ` -Body $body ``` ### Technical Analysis The mandatory `$Guid` parameter is directly interpolated into a hand-built JSON string. PowerShell string interpolation does not perform JSON escaping. A value containing quotation marks, backslashes, or JSON delimiters can therefore corrupt the request or alter its property structure. This is a JSON injection issue rather than PowerShell command injection: the value is not passed to `Invoke-Expression` or executed as code. Nevertheless, the resulting request is authenticated with the user's token and is sent to the remote note-detail API. Other PowerShell scripts in the project use `ConvertTo-Json`; this script should use the same safe serialization mechanism. ### Attack Path 1. An attacker supplies a crafted string and represents it as a note GUID. 2. The user or agent passes that string to `get-note-detail.ps1`. 3. PowerShell interpolates it into `$body` without JSON escaping. 4. The crafted characters alter or invalidate the JSON object. 5. `Invoke-YinxiangPost` sends the modified request with the victim's authorization token. 6. The remote parser either rejects the malformed request or processes an attacker-influenced property structure. ### Impact Assessment The attacker may influence the structure of an authenticated note-detail request. The maximum demonstrated scope is the fixed Yinxiang endpoint and the privileges granted by th ...[truncated 328 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Create a PowerShell object and serialize it with `ConvertTo-Json`: ```powershell param([Parameter(Mandatory)][string]$Guid) . "$PSScriptRoot\_common.ps1" $body = @{ guid = $Guid source = "skill" resultSpec = @{ includeContent = $true includeResources = $false includeTags = $true includeResourceContent = $false } } | ConvertTo-Json -Compress -Depth 5 Invoke-YinxiangPost ` -Uri "https://app.yinxiang.com/third/ai-chat-note/grpc-api/search/getNoteDetail" ` -Body $body ``` Also validate the GUID against its documented syntax, reject excessive input lengths, and add tests for quotes, backslashes, control characters, and embedded JSON fragments. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/save-token.sh:3
Finding
Authorization Token Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/save-token.sh:3-4` **Vulnerability Type**: Sensitive credential exposure through process arguments and shell history **Risk Level**: Low ### Vulnerable Code ```bash # 用法: ./save-token.sh <YX_AUTH_TOKEN> TOKEN="$1" ``` The documented authorization flow also embeds the token in commands such as: ```bash openclaw config set skills.entries.yinxiang-skill.apiKey <Token> && mkdir -p ~/.config/yinxiang-skill && printf '%s' '<Token>' > ~/.config/yinxiang-skill/token && chmod 600 ~/.config/yinxiang-skill/token ``` ### Technical Analysis The token is accepted as a command-line argument. Command arguments may be recorded in shell history, terminal transcripts, agent execution logs, monitoring systems, and process metadata. On systems where process arguments are visible to other local users, the token may also be observable while the command is running. The authorization instructions additionally ask the user to send the token through the conversation and direct the agent to embed it into generated commands. This increases the number of systems that may retain the credential. The Unix token file itself is protected with mode `0600`, but that protection does not remove copies retained in history, logs, chat records, or process listings. ### Attack Path 1. The user obtains a Yinxiang authorization token. 2. The token is sent through chat or passed to `save-token.sh` as a command-line argument. 3. The full invocation is retained in shell history, execution logs, a transcript, or process metadata. 4. A local user or party with access to those records retrieves the token. 5. The exposed token is reused against Yinxiang APIs. 6. The attacker accesses or modifies note resources within the token's authorized scope. ### Impact Assessment A stolen token may allow authenticated access to the victim's Yinxiang account features exposed by these APIs, including reading note details, searching notes, creating not ...[truncated 277 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Read the token from protected standard input instead of a command argument: ```bash IFS= read -r -s -p "Token: " TOKEN printf '\n' ``` - Prefer a platform credential manager or secret-storage service over a plaintext file. - Do not interpolate tokens into agent-generated command text. - Avoid asking users to paste long-lived secrets into retained chat sessions where a delegated OAuth flow is available. - Disable command tracing while handling credentials and ensure logs redact authorization values. - Preserve restrictive file creation atomically: ```bash umask 077 mkdir -p "$HOME/.config/yinxiang-skill" printf '%s' "$TOKEN" > "$HOME/.config/yinxiang-skill/token" ``` - Document token revocation and rotation procedures. - Rotate tokens that may already have been captured in transcripts or logs. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/save-token.ps1:2
Finding
Windows Token File Is Stored Without Explicitly Restrictive Access Controls<![CDATA[ ## Vulnerability Details **File Location**: `scripts/save-token.ps1:2-4` **Vulnerability Type**: Plaintext credential storage with inherited filesystem permissions **Risk Level**: Low ### Vulnerable Code ```powershell $dir = "$HOME\.config\yinxiang-skill" if (!(Test-Path $dir)) { New-Item -ItemType Directory -Path $dir | Out-Null } Set-Content -Path "$dir\token" -Value $Token -NoNewline -Encoding UTF8 ``` ### Technical Analysis The PowerShell implementation writes the authorization token as plaintext and does not establish an explicit access-control list for the directory or file. It relies entirely on inherited permissions from the user's home directory. This differs from the Bash implementation, which applies `chmod 600`. Default Windows home-directory ACLs are often restrictive, but they are not guaranteed to be so on modified, shared, migrated, or enterprise-managed systems. A permissive inherited ACL could allow another account or group to read the token. ### Attack Path 1. A user saves a token through `save-token.ps1`. 2. The destination directory or file inherits an ACL that permits another local principal to read it. 3. That principal reads `$HOME\.config\yinxiang-skill\token`. 4. The principal reuses the token against the fixed Yinxiang API endpoints. 5. Note data and note-management operations become accessible within the token's authorization scope. ### Impact Assessment A successful attack does not provide operating-system privilege escalation, but it may expose all Yinxiang note operations authorized by the token. This can include confidential note content and the ability to create or modify account data. Exploitability depends on the effective inherited Windows ACL. Systems with correctly restricted user-profile permissions may not be directly exposed, while systems with permissive inheritance are vulnerable. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions Prefer Windows Credential Manager or DPAPI-protected storage instead of a plaintext token file. If a file must be used: 1. Create the directory with inheritance disabled. 2. Remove inherited access entries. 3. Grant access only to the current user and, if operationally required, SYSTEM. 4. Verify the resulting ACL after writing the file. 5. Fail closed if restrictive permissions cannot be established. An implementation can use `System.Security.AccessControl.DirectorySecurity` and `FileSecurity`, or carefully constructed `icacls` commands, to limit access to the current account. Do not rely solely on the permissions inherited from the profile directory. The same ACL hardening should be applied to the token-writing commands documented in `SKILL.md`. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (86)

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- 优先使用 `scripts/` 中当前平台对应的脚本或 `references/api-commands.md` 中的命令调用 API;如果参考脚本疑似有误、在当前环境运行异常、输出格式不适合继续处理,或与接口文档/字段声明不一致,不要修改 skill 内置参考脚本,改为以 `references/api-comm
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
param(
    [Parameter(Mandatory)][string]$NoteGuid,
    [string]$Title = "",
    [string]$Content = "",
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Static analysis

No suspicious patterns detected.