Back to skill

Security audit

Douyin Analyzer

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs transcript analysis, but its bundled script silently reads OpenClaw user configuration that is not needed or disclosed.

Review this skill before installing. Its transcript analysis behavior is mostly ordinary, but the bundled script should not need to read your OpenClaw config. Prefer a version that removes that config access or limits it to an explicitly chosen, dedicated config file, and treat transcript text as untrusted when using the generated LLM prompt.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T01 · Skill Instruction Hijacking

Warning
Location
scripts/analyzer.py:305
Finding

Untrusted Transcript Content Embedded Directly into LLM Instructions

Content
View full analysis

Vulnerability Details

File Location: scripts/analyzer.py, lines 305-318
Vulnerability Type: Indirect prompt injection through untrusted transcript content
Risk Level: Medium

Complete Code Snippet

python
def generate_llm_prompt(self, text: str) -> str:
    """生成供 LLM 深度分析的提示词
    
    当 agent 需要更高质量的分析时,可以将此提示词和文本一起发给 LLM
    """
    char_count = len(text)
    est_minutes = round(char_count / 250, 1)
    
    return f"""请对以下转录文本进行深度分析(约 {char_count} 字,估计 {est_minutes} 分钟内容):

1. **语义分段**:按主题/话题将文本分成若干段落,每段加上小标题
2. **核心要点**:提取 3-7 个核心观点或关键信息
3. **内容总结**:用 100-200 字概括全文核心内容
4. **口语化处理**:将口语表达转为书面语,保留所有要点,不做摘要压缩

转录文本:
---
{text[:500]}{'...(已截断,完整文本请直接传入)' if len(text) > 500 else ''}
---"""

Technical Analysis

generate_llm_prompt() directly interpolates attacker-controlled transcript content into an instruction intended for an LLM. The visual delimiter surrounding the transcript does not create an enforceable trust boundary. The generated prompt also contains no explicit instruction requiring the model to treat transcript content solely as untrusted data and to ignore commands found inside it.

An attacker can place instruction-like content in a transcript, such as requests to disregard the analysis task, disclose context, generate deceptive output, or invoke available tools. If the returned llm_prompt is submitted to a tool-enabled agent, the model may interpret the embedded content as executable instructions rather than text to analyze.

The function only embeds the first 500 characters, but this does not prevent exploitation because an attacker can place the malicious instruction at the beginning of the transcript.

Attack Path

  1. An attacker controls or influences a transcript supplied to the analyzer.
  2. The attacker places adversarial LLM instructions within the first 500 characters.
  3. The application calls DouyinAnalyzer.analyze() or `generate_llm_prom ...[truncated 937 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pass transcript content through a separate structured input or data field rather than concatenating it with trusted instructions.
  2. Add an explicit security instruction stating that the transcript is untrusted data and that any commands, policies, or tool requests contained within it must not be followed.
  3. Use clear randomized or structured boundaries where supported, while recognizing that delimiters alone do not prevent prompt injection.
  4. Run transcript analysis with tools disabled unless tool access is strictly necessary.
  5. Apply least privilege to any downstream agent and require confirmation or policy validation before consequential tool operations.
  6. Validate model output against an expected schema and reject responses that contain unexpected commands, tool requests, or unrelated content.
  7. Add adversarial tests containing prompt-injection instructions at the beginning and throughout transcripts.

T05 · Unauthorized Access and Privilege Escalation

Note
Location
scripts/analyzer.py:24
Finding

Unnecessary Automatic Access to User-Level OpenClaw Configuration

Content
View full analysis

Vulnerability Details

File Location: scripts/analyzer.py, lines 24-38 and 83-84
Vulnerability Type: Excessive access to user-level agent configuration
Risk Level: Low

Complete Code Snippet

python
# 配置路径
DEFAULT_CONFIG_PATH = Path.home() / ".openclaw" / "skills" / "douyin-config.json"
FALLBACK_CONFIG_PATH = Path.home() / ".openclaw" / "config.json"


def load_douyin_config() -> Dict:
    """加载抖音模块配置"""
    if DEFAULT_CONFIG_PATH.exists():
        with open(DEFAULT_CONFIG_PATH, 'r', encoding='utf-8') as f:
            return json.load(f)
    if FALLBACK_CONFIG_PATH.exists():
        with open(FALLBACK_CONFIG_PATH, 'r', encoding='utf-8') as f:
            return json.load(f).get("douyin", {})
    return {}
python
def __init__(self, config: Optional[Dict] = None):
    self.config = config or load_douyin_config()

Technical Analysis

Constructing DouyinAnalyzer automatically reads either a dedicated skill configuration file or the broader user-level ~/.openclaw/config.json. The documented task is local transcript cleanup and analysis, and none of the analyzer methods use self.config. Consequently, this filesystem access is unnecessary for the implemented functionality and violates least-privilege principles.

The expression config or load_douyin_config() also means that passing an intentionally empty dictionary does not disable filesystem access. Because an empty dictionary is false-valued, the constructor still calls load_douyin_config().

No code was found that transmits, prints, modifies, or otherwise exposes the loaded configuration. Therefore, the confirmed impact is limited to unnecessary local access rather than demonstrated credential theft or data exfiltration.

Attack Path

  1. A user invokes the documented analyzer script.
  2. main() constructs DouyinAnalyzer() without an explicit configuration.
  3. The constructor invokes `load_douyin_confi ...[truncated 1032 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove configuration loading entirely if it is not needed by the analyzer.

  2. Do not fall back to the general ~/.openclaw/config.json; use a dedicated, narrowly scoped configuration file.

  3. Require explicit opt-in before accessing user-level configuration.

  4. Replace the constructor logic with an explicit None check:

    python
    def __init__(self, config: Optional[Dict] = None):
        self.config = {} if config is None else config
    
  5. If configuration loading becomes necessary, accept an explicit path from the caller and validate that it refers to the intended dedicated configuration.

  6. Document every configuration file accessed and the fields consumed.

  7. Avoid retaining configuration values that are not used, and never include configuration data in analysis output or LLM prompts.

Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

主要不一致点在于实现方式与声明相冲突。描述明确说语义分段、要点提取、总结“由 agent 直接完成,不依赖脚本”,而实际代码块正是一个 analyzer.py 脚本,并且实现了这些分析能力的基础版本,因此这是实质性描述-行为不符。虽然代码的总体领域仍属于“内容分析”,并未表现出明显越权或恶意行为,但它确实承担了原本被声明为不由脚本完成的核心功能。此外,代码还包含文本清理、字符数/时长估算、生成 LLM 深度分析提示词、命令行和文件输入输出等附加行为;这些可视为相关扩展,但不是最核心的偏差。综合判断应标记为 mismatch。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The natural-language instructions and output format are entirely specified in Chinese, including required headings and processing directions, which constrains the skill to a specific language/locale. The file does not offer users a language choice or explain that the locale restriction is required for a region-specific or compliance reason.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generated LLM prompt explicitly instructs the model in Chinese to perform analysis and produce the requested outputs in that language, with no opt-in or alternative locale handling. This is a natural-language locale policy concern because the skill constrains language behavior by default rather than offering a user choice or documenting a justified region-specific requirement.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description explicitly states '由 agent 直接完成,不依赖脚本', implying the skill should not depend on a script implementation. However, this file defines the core text-cleaning, segmentation, extraction, summarization, and command-line execution flow in Python, meaning the functionality does rely on script code rather than being agent-only.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The docstring frames this module as only providing basic preprocessing and says deeper analysis should be performed directly by the agent. Yet the script includes a dedicated generate_llm_prompt capability and exposes it via both the API result and CLI action, which is not a direct contradiction of behavior but does blur the documented boundary between 'agent-direct' and script-provided functionality.

Content

No source excerpt is available for this finding.