Back to skill

Security audit

TikHub API 工具(KK版)

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent TikHub media workflow, but it needs Review because it auto-uses local credentials and contains unsafe download and background transcription code.

Install only after reviewing the TikHub provider trust boundary and replacing local .env scraping with explicit secret configuration. Run it in a dedicated environment with pinned dependencies, restrict outputs to a chosen download directory, avoid arbitrary video_url inputs, and do not use the CPU background Whisper path until shell=True/nohup handling is fixed.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/tikhub.py:303
Finding

Shell Command Injection in Background Whisper Transcription

Content
View full analysis
{log_file} 2>&1 &" subprocess.run(nohup_cmd, shell=True) return output_path ``` ### Technical Analysis The function constructs a shell command by joining command arguments into a single string and executes it with `shell=True`. Values including `audio_path`, `model`, `language`, `output_dir`, and `log_file` are not shell-escaped. Because the shell interprets metacharacters such as semicolons, command substitutions, pipes, redirections, and ampersands, a crafted argument can terminate the intended Whisper command and introduce an additional operating-system command. Although some normal call paths derive the audio path from a downloaded video, `whisper_transcribe` is also publicly exported by `scripts/__init__.py`. Callers can therefore pass malicious values directly. The CPU pipeline also reaches this vulnerable background mode. ### Attack Path 1. An attacker influences a value passed to `whisper_transcribe`, such as `model`, `language`, or `audio_path`. 2. The attacker includes shell syntax in that value, for example a semicolon followed by another command. 3. The value is inserted verbatim into `nohup_cmd`. 4. `subprocess.run(..., shell=True)` passes the assembled string to the system shell. 5. The shell executes both the intended Whisper operation and the injected command. ### Impact Assessment Successful exploitation allows arbitrary command execution with the privileges of the user running the Skill. The injected process could: - Read or modify files ac ...[truncated 374 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/tikhub.py:132
Finding

Path Traversal and Arbitrary File Overwrite in Video Download

Content
View full analysis
str: os.makedirs(output_dir, exist_ok=True) if not video_url: video_url = get_high_quality_url(aweme_id) if not video_url: return None local_path = os.path.join(output_dir, f"{aweme_id}.mp4") headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/120.0.0.0 Safari/537.36", "Referer": "https://www.douyin.com/", } resp = requests.get(video_url, headers=headers, stream=True, timeout=120) downloaded = 0 total = int(resp.headers.get("Content-Length", 0)) with open(local_path, "wb") as f: for chunk in resp.iter_content(chunk_size=1024 * 1024): if chunk: f.write(chunk) downloaded += len(chunk) ``` ### Technical Analysis The `aweme_id` value is inserted directly into a filesystem path without validation. `os.path.join` does not enforce containment beneath `output_dir`: - Traversal components such as `../` can escape the intended download directory. - If the second path is absolute, `os.path.join` discards the preceding `output_dir`. - Opening the resulting path with mode `"wb"` truncates an existing writable file. - Symbolic links are followed, creating an additional overwrite opportunity. Normal Douyin identifiers are numeric, so accepting path separators and arbitrary characters is not necessary for the declared functionality. ### Attack Path 1. An attacker supplies a crafted `aweme_id` containing traversal components or an absolute path. 2. The attacker optionally supplies a controlled `video_url`, avoiding the nee ...[truncated 842 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/tikhub.py:132
Finding

Unrestricted URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
str: os.makedirs(output_dir, exist_ok=True) if not video_url: video_url = get_high_quality_url(aweme_id) if not video_url: return None local_path = os.path.join(output_dir, f"{aweme_id}.mp4") headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/120.0.0.0 Safari/537.36", "Referer": "https://www.douyin.com/", } resp = requests.get(video_url, headers=headers, stream=True, timeout=120) ``` ### Technical Analysis The exported `download_video` function accepts an arbitrary `video_url` and sends a request without validating: - The URL scheme. - The destination hostname. - Resolved IP addresses. - Redirect destinations. - Loopback, link-local, private, or reserved address ranges. - Whether the destination is an expected Douyin or media CDN host. A caller that controls `video_url` can cause the Skill to access services available from the Agent's network context. The response is subsequently written to disk. Arbitrary destination access is broader than required for downloading media from known platform CDN endpoints. ### Attack Path 1. An attacker supplies a URL targeting an internal service, loopback listener, private-network host, or cloud metadata endpoint. 2. The Skill resolves and requests that URL from the Agent's network environment. 3. If the server redirects the request, `requests` follows redirects by default without revalidating the new destination. 4. The internal response is streamed to a local file. 5. A caller with access to the output can inspect the retrieved res ...[truncated 595 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependencies and Unconstrained SDK Installation

Content
View full analysis
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 (31)

Tainted flow: 'HEADERS' from os.environ.get (line 425, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/tikhub.py (reported line 46)May include surrounding context.

python
"""通用 GET 请求"""
    for i in range(retries):
        try:
            resp = requests.get(f"{BASE_URL}{endpoint}", headers=HEADERS, params=params, timeout=30)
            if resp.status_code == 429:
                print(f"⚠️ 频率限制,等待 5 秒... ({i+1}/{retries})")
                time.sleep(5)

Tainted flow: 'HEADERS' from os.environ.get (line 425, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/tikhub.py (reported line 62)May include surrounding context.

python
"""通用 POST 请求"""
    for i in range(retries):
        try:
            resp = requests.post(f"{BASE_URL}{endpoint}", headers=HEADERS, json=json_data, timeout=30)
            if resp.status_code == 429:
                print(f"⚠️ 频率限制,等待 5 秒...")
                time.sleep(5)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

API Key 配置

python
import os
os.environ["TIKHUB_API_KEY"] = "你的KEY"  # 从 .env 读取
os.environ["TIKHUB_BASE_URL"] = "https://api.tikhub.dev"

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

This script opens a specific local .env file path, extracts the TIKHUB_API_KEY, and uses it programmatically. Hard-coded secret-file access inside skill guidance is dangerous because it encourages unauthorized credential retrieval patterns and can be repurposed to access local secrets unrelated to the user's immediate task.

Content

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

md
import httpx

async def check():
    key = open('/Users/kk/.openclaw/workspace/.env').read().split('TIKHUB_API_KEY=')[1].split('\n')[0]
    async with httpx.AsyncClient(timeout=10) as c:
        r = await c.get('https://api.tikhub.dev/api/v1/tikhub/user/get_user_info', headers={'Authorization': f'Bearer {key}'})
        d = r.json()

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Accessing credentials from environment variables is common, but in this skill it is combined with automatic discovery and use of secrets without explicit declaration or consent. In the absence of metadata justifying credential access, this constitutes risky secret handling for an agent skill.

Content

Scanner excerpt · scripts/tikhub.py (reported line 27)May include surrounding context.

python
from pathlib import Path

# ============ 配置区 ============
# 优先从环境变量读取(.env 会由调用方注入),否则尝试从 ~/.openclaw/workspace/.env 加载
API_KEY = os.environ.get("TIKHUB_API_KEY", "")
if not API_KEY:
    env_file = Path.home() / ".openclaw" / "workspace" / ".env"

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

Reading ~/.openclaw/workspace/.env directly is a more serious credential-access issue because it reaches into local storage to harvest a token outside normal explicit configuration flow. In a multi-skill or agent environment, this creates a clear secret-discovery capability that could be repurposed for unauthorized access or exfiltration.

Content

Scanner excerpt · scripts/tikhub.py (reported line 30)May include surrounding context.

python
# 优先从环境变量读取(.env 会由调用方注入),否则尝试从 ~/.openclaw/workspace/.env 加载
API_KEY = os.environ.get("TIKHUB_API_KEY", "")
if not API_KEY:
    env_file = Path.home() / ".openclaw" / "workspace" / ".env"
    if env_file.exists():
        for line in env_file.read_text().splitlines():
            if line.startswith("TIKHUB_API_KEY="):

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code invokes ffmpeg directly and later launches Whisper via subprocess, including a shell-based nohup command path. For an unknown-purpose skill, arbitrary local command execution is a powerful capability that is not inherently justified unless the manifest explicitly states media processing and subprocess use.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This code goes beyond necessary media processing by constructing a shell-backed nohup command that can execute in the background and persist after the invoking process exits. In a skill with unknown trust boundaries, that combination of shell execution and persistence materially increases abuse potential, especially because the command string includes user-influenced path data.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

The tool invocation abuses subprocess parameters by enabling shell=True on a command assembled from variable content. This creates a direct command-injection surface and, because the process is launched under nohup in the background, successful exploitation can yield arbitrary command execution with reduced visibility and longer-lived effects.

Content

Scanner excerpt · scripts/tikhub.py (reported line 317)May include surrounding context.

python
log_file = f"/tmp/whisper_{os.path.basename(audio_path)}.log"
        nohup_cmd = f"nohup {' '.join(cmd)} > {log_file} 2>&1 &"
        print(f"🚀 Whisper 后台转写启动,日志: {log_file}")
        subprocess.run(nohup_cmd, shell=True)
        print(f"📝 文字稿将保存到: {output_path}")
        print(f"⏱️  medium 模型 CPU 转写 1 分钟音频约需 1-2 分钟,请耐心等待")
        return output_path

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill relies on third-party MCP/API services and stored API credentials but does not warn that video identifiers, metadata, and authentication tokens are sent off-host. This omission can mislead users about privacy and trust boundaries when interacting with external platforms.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill instructs users to download subtitle files locally without warning about file creation, storage location, or persistence. This can lead to unanticipated writes, disk consumption, and retention of potentially sensitive media-derived data on the local system.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The balance-check example unnecessarily reads the local .env file directly to extract an API key and then transmits it to a third-party API. That behavior is broader than the stated content-retrieval/transcription purpose and normalizes secret access patterns inside a skill, increasing the risk of credential exposure or reuse in unintended contexts.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

The documented script sends an Authorization bearer token to an external service endpoint. While external communication is expected for this type of integration, the direct use of a locally extracted secret in ad hoc code raises the risk of accidental credential disclosure, misuse, or execution in an untrusted environment.

Content

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

md
async def check():
    key = open('/Users/kk/.openclaw/workspace/.env').read().split('TIKHUB_API_KEY=')[1].split('\n')[0]
    async with httpx.AsyncClient(timeout=10) as c:
        r = await c.get('https://api.tikhub.dev/api/v1/tikhub/user/get_user_info', headers={'Authorization': f'Bearer {key}'})
        d = r.json()
        print('余额:', d['user_data']['balance'], '美元')

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill silently reads a bearer token from both the environment and a local ~/.openclaw/workspace/.env file despite having no manifest or user-visible disclosure justifying local credential access. In an agent-skill context, implicit secret discovery is risky because users may invoke the skill without realizing it will harvest and use locally stored credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code reads an API key from a local .env file without user-facing warning, consent, or manifest justification. In a skill ecosystem, undeclared secret access is dangerous because it normalizes hidden credential harvesting and can surprise users who did not intend to grant this capability.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/tikhub.py (reported line 62)May include surrounding context.

python
"""通用 POST 请求"""
    for i in range(retries):
        try:
            resp = requests.post(f"{BASE_URL}{endpoint}", headers=HEADERS, json=json_data, timeout=30)
            if resp.status_code == 429:
                print(f"⚠️ 频率限制,等待 5 秒...")
                time.sleep(5)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/tikhub.py (reported line 272)May include surrounding context.

python
"""
    if not output_path:
        output_path = video_path.rsplit(".", 1)[0] + ".wav"
    result = subprocess.run([
        "ffmpeg", "-i", video_path, "-vn",
        "-acodec", "pcm_s16le", "-ar", "16000", "-ac", "1",
        output_path, "-y"

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code sets the Whisper transcription language default to "Chinese", and the surrounding docstring describes that language as the expected mode rather than presenting it as a user-selected option. This is a natural-language locale policy issue because it biases output language behavior without explicit user opt-in or a documented region-specific justification.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% 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 · scripts/tikhub.py (reported line 297)May include surrounding context.

python
model: tiny/base/small/medium/large,medium 精度速度平衡好
        language: 语言代码,Chinese
        output_path: 可选,文字稿输出路径
        background: True 用 nohup 后台跑(推荐,CPU 慢);False 同步等待
    返回: 文字稿文件路径(后台模式立即返回路径,不等待完成)
    """
    if not output_path:

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

Using nohup to detach the transcription process allows it to continue running independently of the caller, creating persistence beyond the expected session lifecycle. In a skill environment this is dangerous because it weakens operator visibility and control, and it compounds the impact of the shell-injection issue in the same code path.

Content

Scanner excerpt · scripts/tikhub.py (reported line 315)May include surrounding context.

python
if background:
        log_file = f"/tmp/whisper_{os.path.basename(audio_path)}.log"
        nohup_cmd = f"nohup {' '.join(cmd)} > {log_file} 2>&1 &"
        print(f"🚀 Whisper 后台转写启动,日志: {log_file}")
        subprocess.run(nohup_cmd, shell=True)
        print(f"📝 文字稿将保存到: {output_path}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

The code builds a shell command string from user-influenced values and executes it with shell=True via nohup. Because audio_path contributes to the command and is joined without shell escaping, an attacker can craft a filename containing shell metacharacters to execute arbitrary commands and leave them running in the background.

Content

Scanner excerpt · scripts/tikhub.py (reported line 317)May include surrounding context.

python
log_file = f"/tmp/whisper_{os.path.basename(audio_path)}.log"
        nohup_cmd = f"nohup {' '.join(cmd)} > {log_file} 2>&1 &"
        print(f"🚀 Whisper 后台转写启动,日志: {log_file}")
        subprocess.run(nohup_cmd, shell=True)
        print(f"📝 文字稿将保存到: {output_path}")
        print(f"⏱️  medium 模型 CPU 转写 1 分钟音频约需 1-2 分钟,请耐心等待")
        return output_path

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/tikhub.py (reported line 322)May include surrounding context.

python
print(f"⏱️  medium 模型 CPU 转写 1 分钟音频约需 1-2 分钟,请耐心等待")
        return output_path
    else:
        result = subprocess.run(cmd, capture_output=True, text=True)
        if result.returncode != 0:
            print(f"❌ Whisper 错误: {result.stderr[-300:]}")
        print(f"📝 转写完成: {output_path}")

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The example hard-codes language="zh" for transcription, which imposes a specific language/locale choice without documenting that it is optional or user-selectable. This can violate language/locale policy when the skill is used in broader contexts beyond Chinese-only content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The description field is written entirely in Chinese and labels the skill in that locale without any indication of multilingual support or user opt-in. This can constitute a language/locale policy issue because the manifest presents a fixed language choice rather than offering flexibility or documenting a justified locale constraint.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The dependency requests is unpinned, so builds may install different versions over time, including versions with known security issues or breaking changes. This weakens supply-chain integrity and makes it impossible to verify that a safe release is consistently deployed.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests
openai-whisper
mlx-whisper
ffmpeg

Static analysis

No suspicious patterns detected.