Back to skill

Security audit

Douyin Upload

Security checks for vulnerabilities and agentic risk

Overview

This skill automates posting to a real Douyin account, but it lacks a final publish confirmation and contains unsafe command and install behavior that users should review first.

Review carefully before installing. Use only with a test Douyin account until a confirmation gate is added, avoid themes containing shell metacharacters, do not install the bundled sau.sh as a trusted sau command, and avoid running install.sh until dependency pinning and .env handling are fixed.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish.py:153
Finding

Shell Command Injection Through User-Controlled Theme and Generated File Paths

Content
View full analysis
str: """ Prepare the publishing command. Args: article_path: Article file path cover_path: Cover image file path Returns: Complete publishing command """ command = f"{PUBLISH_CONFIG['sau_command']} {PUBLISH_CONFIG['platform']} {PUBLISH_CONFIG['account_name']} upload-article \"{article_path}\" --cover \"{cover_path}\"" return command def execute_publish_command(self, command: str) -> Dict[str, Any]: """ Execute the publishing command. Args: command: Publishing command Returns: Publishing result dictionary """ print(f"Executing publishing command: {command}") try: result = subprocess.run( command, shell=True, capture_output=True, text=True, timeout=300 ) ``` The input validation permits nearly all shell metacharacters: ```python def validate_theme(self, theme: str) -> bool: if not theme or not isinstance(theme, str) or len(theme.strip()) == 0: return False if len(theme) > 100: return False return True ``` The theme is subsequently embedded in an article filename: ```python timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"article_{theme.replace(' ', '_')}_{timestamp}.md" filepath = os.path.join(ARTICLES_DIR, filename) with open(filepath, "w", encoding="utf-8") as f: f.write(full_content) ``` ### Technical Analysis The publisher constructs one command string and executes it through a shell. The article and cover paths are enclosed in double quotes, but embedded double quotes, comma ...[truncated 2194 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/install.sh:41
Finding

Unsafe Creation and Unconditional Overwrite of Credential Configuration

Content
View full analysis
~/.openclaw/extensions/douyin/skills/douyin-upload/.env << 'EOF' # Douyin publishing Skill environment configuration OPENAI_API_KEY=your_openai_api_key_here EOF ``` ### Technical Analysis The installer writes to a fixed credential-related path using ordinary shell redirection. It does not: - Refuse to overwrite an existing configuration. - Verify that the destination is a regular file rather than a symbolic link. - Create or validate the parent directory. - Set a restrictive umask. - Enforce permissions such as mode `0600`. - Preserve an existing API key during reinstallation. If the file is later edited to contain a real OpenAI API key, its permissions depend on the invoking user's umask. On systems with a permissive umask, other local users may be able to read it. The runtime code only calls `os.getenv("OPENAI_API_KEY")`; it does not load this `.env` file. The installer therefore creates a sensitive storage location that is not directly required by the current implementation. ### Attack Path A symbolic-link attack is possible when another local process or user can prepare the destination within the victim-controlled installation tree: 1. The destination parent directory exists. 2. An attacker causes `.env` to be a symbolic link to another file writable by the victim. 3. The victim runs `scripts/install.sh`. 4. Shell redirection follows the symbolic link and truncates the linked file. 5. The placeholder configuration is written to the linked destination. A confidentiality failure can occur as follows: 1. The installer creates `.env` under a permissive umask. 2. The user replaces the placeholder with a real API key. 3. Another local us ...[truncated 663 chars]
Remediation
View remediation
&2 exit 1 fi if [ -e "$config_file" ]; then echo "Configuration already exists; leaving it unchanged." else install -m 600 /dev/null "$config_file" printf '%s\n' \ '# Douyin publishing Skill environment configuration' \ 'OPENAI_API_KEY=' > "$config_file" fi ``` 3. Never print real secret values to logs or command output. 4. Document that the key is used only for OpenAI image generation. 5. If `.env` remains supported, load it through a reviewed mechanism and confirm that it cannot override security-sensitive environment variables unexpectedly. 6. Add `.env` to version-control ignore rules and verify permissions before use. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:4
Finding

Unpinned, Unhashed, and Incorrectly Named Runtime Dependencies

Content
View full analysis
=9.0.0 # Optional dependencies requests>=2.31.0 # Development dependencies pytest>=7.0.0 ``` The installer resolves these packages in the active environment: ```bash # Install Python dependencies echo "Installing Python dependencies..." pip install -r scripts/requirements.txt ``` ### Technical Analysis The dependencies use open-ended lower bounds rather than exact, reviewed versions. No package hashes are supplied, and the installer uses whichever package index and `pip` configuration are active on the host. The code imports the maintained `PIL` module namespace, but the package normally used to provide it is `Pillow`. Listing `PIL` as the distribution name is inconsistent with the project's own documentation, which separately tells users to install `Pillow`. Incorrect or ambiguous distribution names increase the risk of installing an unintended package or causing installation failure. The installer also includes `pytest`, a development dependency that is not required for the Skill's publishing workflow. Every unnecessary package increases the supply-chain and transitive-dependency attack surface. No virtual environment is created, so packages may be installed into and modify the user's ambient Python environment. ### Attack Path 1. A user runs `scripts/install.sh`. 2. The script invokes the ambient `pip` executable. 3. `pip` resolves mutable package versions from the currently configured index or mirror. 4. A compromised index, malicious mirror, dependency-confusion condition, or unintended distribution name supplies a hostile package or future hostile version. 5. Package installation hooks execute with the privileges of the user running the ...[truncated 858 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/generate_image.py:116
Finding

Unbounded and Insufficiently Validated Remote Image Download

Content
View full analysis
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Warning
Location
sau.sh:1
Finding

Developer-Specific Wrapper Can Redirect Trusted sau Calls to Unreviewed External Code

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

Tainted flow: 'headers' from os.getenv (line 110, 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/generate_image.py (reported line 116)May include surrounding context.

python
}
            
            # 生成图片的请求
            response = requests.post(
                "https://api.openai.com/v1/images/generations",
                headers=headers,
                json={

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code chunk is limited to local content generation and saving markdown files. It creates article text, tags, and filenames, and writes the result under the articles directory. Although it creates an images directory, there is no image generation logic, no network/API interaction, no subprocess/CLI execution, and no publishing action to Douyin. Therefore the code materially under-implements the declared end-to-end purpose of generating content plus cover images and publishing via sau.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The supplied code is limited to an image-generation module. Its behavior centers on choosing keywords and styles from a theme, generating an image prompt, calling the OpenAI images API if an API key is present, or creating a simple synthetic image with PIL, then saving the image file locally. The declared description presents a broader end-to-end Douyin article automation workflow: generating article markdown, generating cover images, and publishing to Douyin using sau. Those core capabilities are not present in this code chunk. Because the actual code implements only one supporting subset of the declared workflow and also makes an undeclared outbound API call plus filesystem writes, the description does not accurately represent this specific code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk is specifically a publisher module, not a full workflow that generates engaging markdown content and cover images. It checks for the sau CLI, searches local article and cover files matching a theme, validates file existence and size, executes an upload command, parses the response, and logs results. Publishing to Douyin is consistent with the description, but the description materially overstates the implemented capabilities by including content and image generation from a topic. Therefore the declared description does not accurately represent what this supplied code chunk actually does.

Content

No source excerpt is available for this finding.

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 · references/README.md (reported line 69)May include surrounding context.

md
# 创建环境变量配置文件
echo "创建环境变量配置..."
cat > ~/.openclaw/extensions/douyin/skills/douyin-upload/.env << 'EOF'
# 抖音发布技能环境变量配置
OPENAI_API_KEY=your_openai_api_key_here
EOF

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 · scripts/install.sh (reported line 43)May include surrounding context.

sh
# 创建环境变量配置文件
echo "创建环境变量配置..."
cat > ~/.openclaw/extensions/douyin/skills/douyin-upload/.env << 'EOF'
# 抖音发布技能环境变量配置
OPENAI_API_KEY=your_openai_api_key_here
EOF

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 · scripts/install.sh (reported line 52)May include surrounding context.

sh
echo "✓ 抖音发布技能安装完成!"
echo ""
echo "配置说明:"
echo "  1. 复制上面的配置到 ~/.openclaw/extensions/douyin/skills/douyin-upload/.env"
echo "  2. 修改为你的实际配置"
echo "  3. 使用时运行: python3 scripts/main.py '你的主题'"
echo ""

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a true tool-parameter-abuse issue because a shell is invoked on a formatted command string assembled from multiple values rather than fixed arguments. In the context of an automation skill that discovers files and publishes externally, any attacker influence over config, environment, or filenames can turn a publishing action into arbitrary OS command execution, making the skill materially more dangerous.

Content

Scanner excerpt · scripts/publish.py (reported line 177)May include surrounding context.

python
try:
            # 执行命令
            result = subprocess.run(
                command,
                shell=True,
                capture_output=True,

Possible Typosquatting: 'PIL' resembles popular package 'pip'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares no explicit tool scope or permissions while its documented workflow implies use of shell commands, local files, networked APIs, and possibly environment secrets. Missing scope boundaries increases the chance an agent will invoke higher-risk capabilities than the user expects, especially for an auto-publishing workflow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill repeatedly frames publishing as an automatic step and does not require explicit user confirmation immediately before the irreversible post action. For a social-media account operation, this is dangerous because generated or mistaken content could be publicly published without informed consent, causing reputational, legal, or policy-compliance consequences.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger conditions are broad enough to match many ordinary content-creation requests, which increases the chance the agent activates an auto-publishing skill in situations where the user did not intend publication. In the context of a social-media publishing skill, accidental activation can lead to unwanted account actions, disclosure of draft content, or reputational harm.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README repeatedly promotes one-click automated publishing to a live Douyin account but does not clearly warn users that invoking the skill can post directly to a real account. In an automation skill, missing this warning increases the chance of accidental publication, reputational damage, and misuse, especially when users may test with production credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The examples show commands and code that generate content, call OpenAI-backed services, and publish to a real Douyin account, but they do not warn users that topic data and generated content may be transmitted to third-party services or that running the command can perform account-impacting actions. In this skill context, that omission is meaningful because the feature is explicitly designed to automate external publication, so users may trigger network/API usage and posting without informed consent safeguards in the documentation.

Content

No source excerpt is available for this finding.

File System Enumeration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Content

Scanner excerpt · references/examples.md (reported line 142)May include surrounding context.

bash
# 查看最新的发布日志
ls -la ~/.openclaw/workspace/logs/ | grep process_log_ | tail -5

# 查看详细的发布结果
cat ~/.openclaw/workspace/logs/process_log_*.json | python -m json.tool

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The configuration hard-codes the content generation language to "zh-CN", which is a natural-language locale restriction. Under the policy, forcing a specific language without offering user choice or documenting justified regional scope is a violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module description and all user-facing strings are written in Chinese, which imposes a specific language on users without any opt-in or alternative locale handling. Under the policy for natural-language violations, forcing a language without user choice is in scope for all file types.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module description is written as a China-specific Douyin publishing skill and all user-facing strings and prompts are hard-coded in Chinese. There is no indication that the user can opt into another language or locale, which matches the policy concern for forced language/locale behavior.

Content

No source excerpt is available for this finding.

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 · scripts/generate_image.py (reported line 116)May include surrounding context.

python
}
            
            # 生成图片的请求
            response = requests.post(
                "https://api.openai.com/v1/images/generations",
                headers=headers,
                json={

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/generate_image.py (reported line 116)May include surrounding context.

python
}
            
            # 生成图片的请求
            response = requests.post(
                "https://api.openai.com/v1/images/generations",
                headers=headers,
                json={

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 · scripts/generate_image.py (reported line 117)May include surrounding context.

python
# 生成图片的请求
            response = requests.post(
                "https://api.openai.com/v1/images/generations",
                headers=headers,
                json={
                    "model": "dall-e-3",

Tainted flow: 'image_url' from requests.post (line 129, network input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
86% confidence
Finding

The code takes an image URL returned by a remote API and fetches it without validating the host, scheme, or response size. If the upstream response were malicious or compromised, this could enable unexpected outbound requests, SSRF-like behavior, or downloading untrusted content that may exhaust resources or poison downstream processing.

Content

Scanner excerpt · scripts/generate_image.py (reported line 132)May include surrounding context.

python
image_url = data["data"][0]["url"]
                
                # 下载并保存图片
                image_data = requests.get(image_url).content
                return self.save_generated_image(image_data, prompt)
            else:
                print(f"DALL-E API错误: {response.status_code}, {response.text}")

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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/install.sh (reported line 21)May include surrounding context.

sh
# 创建必要的目录
echo "创建必要的目录..."
mkdir -p ~/.openclaw/workspace/logs
mkdir -p ~/.openclaw/workspace/articles
mkdir -p ~/.openclaw/workspace/images
mkdir -p ~/.openclaw/workspace/temp

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest describes a Douyin article automation workflow centered on generating content and publishing with the sau CLI, but this installer also creates configuration for an external OpenAI API credential. That external AI-service dependency is not mentioned in the stated scope, so requiring users to manage a separate model provider credential is an additional capability not clearly justified by the manifest text.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script unconditionally writes a credential-related .env file in the user's home directory without checking whether the file already exists or warning about overwriting sensitive configuration. This can destroy an existing secret configuration or cause users to store credentials in a predictable location without understanding the security implications.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.