Back to skill

Security audit

xeon_asr

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real local TTS/voice-cloning integration, but it exposes powerful unauthenticated local services and installs persistent background services automatically.

Review before installing. Run it only on a trusted machine, prefer firewalling or changing the Node gateway to bind to 127.0.0.1, do not expose port 9002 to a LAN or the internet, and inspect the systemd units and OpenClaw config changes. Avoid running the installer as root except where package installation truly requires it.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
server.js:678
Finding

Unauthenticated TTS Gateway Exposed on All Network Interfaces

Content
View full analysis
{ try { if (req.method === 'GET' && req.url === '/health') { return sendJson(res, 200, { status: 'ok', port: config.port }); } if (req.method === 'GET' && req.url.startsWith('/api/session/state')) { const url = new URL(req.url, 'http://127.0.0.1'); const sessionId = url.searchParams.get('sessionId') || config.openclawSession; const userId = url.searchParams.get('userId') || 'anonymous'; const current = getSessionState(sessionId, userId).session; return sendJson(res, 200, { success: true, session: current }); } if (req.method === 'POST' && req.url === '/api/workflow/message') { const body = await readJsonBody(req); const result = await handleWorkflowMessage(body || {}); return sendJson(res, 200, result); } if (req.method === 'POST' && req.url === '/api/workflow/reference-audio') { const parsed = await parseMultipart(req); // Audio processing and storage follow without authentication. } if (req.method === 'POST' && req.url === '/api/tts/custom-speak') { const body = await readJsonBody(req); const result = await synthesizeCustomVoice({ text: body.text, style: body.style || '普通', language: body.language || config.defaultLanguage, speakerId: body.speakerId || config.defaultSpeaker, }); return sendJson(res, 200, { success: true, ...result }); } if (req.method === 'POST' && req.url === '/api/tts/clone-speak') { const body = await readJsonBody(req); const result = await synthesizeClonedVoice({ text: body.text, referenceAudioPath: body.referenceAudioPath, language: body.language || config.defaultLanguage, ...[truncated 2064 chars]
Remediation
View remediation
{ // ... }); ``` 2. Require a cryptographically random API token on every non-health endpoint. 3. Compare tokens using a timing-safe comparison and store them outside source-controlled configuration. 4. Enforce authorization so callers can only access state belonging to their own session and user identity. 5. If remote access is required, place the service behind a mutually authenticated TLS reverse proxy. 6. Apply firewall rules that limit port 9002 to trusted local or management interfaces. 7. Add request rate limits, audit logging, and inference quotas. 8. Avoid returning internal filesystem paths and detailed internal errors to untrusted callers. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
server.js:526
Finding

Arbitrary Local File Read Through the Clone-Speak Endpoint

Content
View full analysis
({})); if (!response.ok || data.success === false) { throw new Error(data.error || `音色克隆请求失败 (${response.status})`); } const outputPath = uniqueOutputPath('clone'); fs.writeFileSync(outputPath, Buffer.from(data.audio_base64, 'base64')); cleanupManagedFiles(); return { mode: 'voice_clone', outputPath, sampleRate: data.sample_rate, estimatedSeconds: timing.estimatedSeconds, }; } ``` ```javascript i ...[truncated 2150 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
setup_env.sh:253
Finding

Python Code Injection Through Installer Environment Variables

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
setup_env.sh:27
Finding

Mutable and Unverified Python Dependencies Are Installed During Setup

Content
View full analysis
/dev/null 2>&1 || \ pip install -q huggingface_hub >/dev/null 2>&1; then # Resolve the newly installed CLI. fi ``` ### Technical Analysis The installation process retrieves mutable package versions from the active Python package index. Exact versions are not pinned, hashes are not checked, and no locked transitive dependency set is supplied. The `--upgrade` option causes future installations to select newer releases even when an older tested release is already available. In addition, `XDP_TTS_PIP_SPEC` can redirect installation to a different package, wheel, URL, or package-index-resolved specification. This flexibility is useful for development but expands the supply-chain trust boundary. No evidence shows that the named packages are currently malicious. The vulnerability is the absence of deterministic version and integrity controls, which permits a compromised package release, account, mirror, or configured index to alter the code executed during installation. ### Attack Path 1. An attacker compromises a package publisher, package-index account, configured mirror, DNS/network trust path, or installation environment. 2. The ...[truncated 801 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
server.js:270
Finding

Missing Request and Upload Limits Permit Resource Exhaustion

Content
View full analysis
{ const chunks = []; req.on('data', (chunk) => chunks.push(chunk)); req.on('end', () => { try { const text = Buffer.concat(chunks).toString('utf8'); resolve(text ? JSON.parse(text) : {}); } catch (error) { reject(error); } }); req.on('error', reject); }); } ``` ```javascript function parseMultipart(req) { const form = new formidable.IncomingForm({ uploadDir: config.runtimeDir, keepExtensions: true, multiples: false, }); return new Promise((resolve, reject) => { form.parse(req, (error, fields, files) => { if (error) { reject(error); return; } resolve({ fields, files }); }); }); } ``` ### Technical Analysis `readJsonBody` accumulates all request chunks in memory and only parses the body after the client finishes sending it. It does not check `Content-Length`, track received bytes, or terminate oversized requests. The multipart parser specifies an upload directory but does not explicitly configure project-appropriate `maxFileSize`, `maxTotalFileSize`, or field limits. The server also has no visible per-client rate limiting, request timeout policy, or TTS concurrency cap. Because the gateway is unauthenticated and listens on all interfaces, these missing controls are directly reachable by network peers. ### Attack Path 1. An attacker connects to port 9002. 2. The attacker sends a very large JSON body to a JSON endpoint, causing all chunks to remain resident in memory. 3. Alternatively, the attacker submits repeated large multipart uploads to an audio endpoint. 4. Concurrent slow requests can hold sockets and parser state, while completed upl ...[truncated 590 chars]
Remediation
View remediation
{ received += chunk.length; if (received > MAX_JSON_BYTES) { req.destroy(new Error('Request body too large')); return; } chunks.push(chunk); }); ``` 2. Configure explicit multipart constraints: ```javascript new formidable.IncomingForm({ uploadDir: config.runtimeDir, keepExtensions: true, multiples: false, maxFileSize: 10 * 1024 * 1024, maxTotalFileSize: 10 * 1024 * 1024, maxFields: 10, }); ``` 3. Remove partial temporary files on every parse, validation, timeout, and processing failure. 4. Set request-header, request-body, idle-socket, and upstream-fetch timeouts. 5. Apply per-client rate limits and authenticated quotas. 6. Limit concurrent TTS jobs and queue excess requests. 7. Monitor runtime-directory disk use and reject uploads before the filesystem reaches a critical threshold. 8. Bind the service to localhost unless remote access is explicitly required. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (41)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · setup_env.sh (reported line 117)May include surrounding context.

sh
if [[ ! -d "$conda_dir" ]]; then
    wget --timeout=120 -q "$conda_url" -O /tmp/miniconda.sh || curl -fsSL --connect-timeout 120 "$conda_url" -o /tmp/miniconda.sh
    bash /tmp/miniconda.sh -b -p "$conda_dir" >/dev/null 2>&1
    rm -f /tmp/miniconda.sh
  fi
  PYTHON_CMD="$conda_dir/bin/python"
  [[ -x "$PYTHON_CMD" ]] || { log_error "Miniconda 安装失败"; exit 1; }

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The configuration example sets defaultLanguage to Chinese, which establishes a language preference by default. Under the policy, forcing a specific language without explicit user choice or opt-in is a natural-language locale violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 193)May include surrounding context.

bash stop_tts.sh bash self_check.sh

curl http://127.0.0.1:5002/api/health curl http://127.0.0.1:9002/health

text

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file’s operational instructions, trigger guidance, and user-facing behavior are all specified only in Chinese. This can constitute a language-policy violation when a skill effectively forces a specific language without user opt-in or a documented regional constraint.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This manifest-style config sets a single defaultLanguage value of "Chinese" with no accompanying indication that users can choose another language or that the skill is intended only for Chinese-language use. In configuration and descriptive text, forcing a specific language by default can violate the language/locale policy when no user opt-in or justification is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The config contains a natural-language setting, defaultLanguage: "Chinese", that establishes a specific language choice for the skill. There is no visible indication in this file that users may select another language or that the Chinese-only default is required for a documented regional purpose.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The comment/log line states that xeontts will not modify related configuration in a way that causes conflicts, but the script actively edits the OpenClaw config file and deletes config.skills.xeontts if present at L69-L74. This is not merely incomplete documentation; it gives a reassuring statement about non-interference while the script performs broader config mutation than the message suggests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Multiple log and error strings are presented only in Chinese, including unknown-argument errors and installation progress messages. This imposes a fixed locale on users with no documented language selection or opt-in, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The installer invokes a script to install systemd auto-start services, which creates persistence on the host, but it does so without any confirmation prompt, explicit warning, or clear opt-in at that point in execution. Persistent service installation increases the security and operational impact of the package because it causes code to run automatically after reboot and may surprise users who expected only a local/manual setup.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script silently creates persistent user systemd unit files for two services without any prior warning, prompt, or dry-run mode. Modifying a user's startup configuration is a security-relevant action because it establishes persistence and changes execution behavior beyond the current session, which is especially risky in an agent skill context where users may not expect background services to be installed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script immediately enables and starts long-running services with systemctl --user enable --now, but only informs the user after the services are already active. Immediate launch of background processes can expose local network listeners or persistent automation unexpectedly, and in a skill package this can materially change the user's environment without informed consent.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
98% confidence
Finding

systemctl --user enable --now "$TTS_UNIT_NAME" establishes login-session persistence for the TTS service and starts it immediately. Persistence mechanisms are security-sensitive because they cause code to execute automatically in future sessions; in this script, that behavior is applied without user confirmation and launches a service bound to localhost on every login.

Content

Scanner excerpt · install_systemd_services.sh (reported line 60)May include surrounding context.

sh
EOF

systemctl --user daemon-reload
systemctl --user enable --now "$TTS_UNIT_NAME"
systemctl --user enable --now "$NODE_UNIT_NAME"
echo "xeontts 开机自启已启用"

Session Persistence

Medium
Category
Rogue Agent
Confidence
98% confidence
Finding

systemctl --user enable --now "$NODE_UNIT_NAME" similarly creates persistent auto-start behavior for the Node gateway service. In an agent skill context, undisclosed persistence is more dangerous because it can leave always-on helper processes running after the user believes the skill completed, expanding attack surface and complicating detection.

Content

Scanner excerpt · install_systemd_services.sh (reported line 61)May include surrounding context.

sh
systemctl --user daemon-reload
systemctl --user enable --now "$TTS_UNIT_NAME"
systemctl --user enable --now "$NODE_UNIT_NAME"
echo "xeontts 开机自启已启用"

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · self_check.sh (reported line 78)May include surrounding context.

sh
fi

log_step "检查 systemd 状态"
if systemctl --user is-enabled xeontts-tts.service >/dev/null 2>&1; then pass "xeontts-tts.service 已启用"; else fail "xeontts-tts.service 未启用"; fi
if systemctl --user is-enabled xeontts-node.service >/dev/null 2>&1; then pass "xeontts-node.service 已启用"; else fail "xeontts-node.service 未启用"; fi

if [[ "$FAIL_COUNT" -gt 0 ]]; then

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · self_check.sh (reported line 79)May include surrounding context.

sh
fi

log_step "检查 systemd 状态"
if systemctl --user is-enabled xeontts-tts.service >/dev/null 2>&1; then pass "xeontts-tts.service 已启用"; else fail "xeontts-tts.service 未启用"; fi
if systemctl --user is-enabled xeontts-node.service >/dev/null 2>&1; then pass "xeontts-node.service 已启用"; else fail "xeontts-node.service 未启用"; fi

if [[ "$FAIL_COUNT" -gt 0 ]]; then

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill sets defaultLanguage to Chinese, and multiple synthesis paths use body.language || config.defaultLanguage or options.language || config.defaultLanguage, causing Chinese to be applied automatically when the user does not explicitly choose a language. This is a natural-language locale policy issue because the skill imposes a specific language by default rather than offering a user choice or documenting a justified regional constraint.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup_env.sh (reported line 75)May include surrounding context.

sh
check_sudo() {
  if [[ "$EUID" -eq 0 ]]; then
    SUDO=""
  elif command -v sudo >/dev/null 2>&1; then
    SUDO="sudo"
  else
    SUDO=""

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup_env.sh (reported line 84)May include surrounding context.

sh
check_sudo() {
  if [[ "$EUID" -eq 0 ]]; then
    SUDO=""
  elif command -v sudo >/dev/null 2>&1; then
    SUDO="sudo"
  else
    SUDO=""

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup_env.sh (reported line 90)May include surrounding context.

sh
case "$os_id" in
    ubuntu|debian)
      log_step "安装系统依赖 (Debian/Ubuntu)"
      $SUDO apt-get update -qq >/dev/null 2>&1 || true
      $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg >/dev/null 2>&1 || \
        $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg
      ;;

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup_env.sh (reported line 91)May include surrounding context.

sh
case "$os_id" in
    ubuntu|debian)
      log_step "安装系统依赖 (Debian/Ubuntu)"
      $SUDO apt-get update -qq >/dev/null 2>&1 || true
      $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg >/dev/null 2>&1 || \
        $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg
      ;;

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup_env.sh (reported line 92)May include surrounding context.

sh
case "$os_id" in
    ubuntu|debian)
      log_step "安装系统依赖 (Debian/Ubuntu)"
      $SUDO apt-get update -qq >/dev/null 2>&1 || true
      $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg >/dev/null 2>&1 || \
        $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg
      ;;

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup_env.sh (reported line 98)May include surrounding context.

sh
case "$os_id" in
    ubuntu|debian)
      log_step "安装系统依赖 (Debian/Ubuntu)"
      $SUDO apt-get update -qq >/dev/null 2>&1 || true
      $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg >/dev/null 2>&1 || \
        $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg
      ;;

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · setup_env.sh (reported line 99)May include surrounding context.

sh
case "$os_id" in
    ubuntu|debian)
      log_step "安装系统依赖 (Debian/Ubuntu)"
      $SUDO apt-get update -qq >/dev/null 2>&1 || true
      $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg >/dev/null 2>&1 || \
        $SUDO apt-get install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg
      ;;

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · setup_env.sh (reported line 99)May include surrounding context.

sh
local pkg_mgr="yum"
      command -v dnf >/dev/null 2>&1 && pkg_mgr="dnf"
      $SUDO "$pkg_mgr" install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg which >/dev/null 2>&1 || \
        $SUDO "$pkg_mgr" install -y wget curl git lsof net-tools unzip bzip2 ca-certificates ffmpeg which
      ;;
    *)
      log_warn "未知系统,跳过系统依赖自动安装"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

When --force is used, the script recursively removes $HOME/miniconda3, which can destroy an existing Python environment and installed packages. The file does not present a specific user confirmation or explicit warning that this deletion will occur before executing it.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution, suspicious.install_untrusted_source, suspicious.potential_exfiltration

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
self_check.sh:41

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
.clawhub.json:13

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
config.example.json:3

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
server.js:149