T03 · Remote Payload Retrieval and Execution
- Location
SKILL.md:62- Finding
Unverified Remote Installers Are Piped Directly into Shells
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent Gemini image generator, but it has review-worthy risks from unverified installer commands and broad automatic loading of shared .env secrets.
Review this skill before installing. Use only a dedicated Gemini API key, prefer explicit command-line or skill-local configuration, avoid storing unrelated secrets in shared .env files, avoid the curl-to-shell installer paths, and only configure base URLs you trust to receive your prompts and images.
SKILL.md:62Unverified Remote Installers Are Piped Directly into Shells
scripts/generate_image.py:2Executable Dependencies and Installers Are Not Pinned to Immutable Versions
scripts/generate_image.py:657API-Controlled Image URLs Can Trigger Server-Side Request Forgery
scripts/generate_image.py:50Skill Loads All Variables from Shared Credential Files Instead of Required Gemini Settings
The activation text is broad enough to trigger on many ordinary requests related to drawing, logos, posters, editing, or generic image tasks. Over-broad activation can cause the skill to run unexpectedly, increasing the chance of unnecessary data transmission, shell execution, or external API use without clear user intent.
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.
brew install python3
# Ubuntu/Debian
sudo apt update && sudo apt install python3 python3-pip
#CentOS/RHEL
sudo yum install python3 python3-pip
The pipe into sh is dangerous command chaining because it turns remote content retrieval directly into code execution. In context, this materially increases risk beyond ordinary installation instructions by removing opportunities for user inspection or integrity checks.
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# 使用 pip
pip install uv
This command downloads and executes an external install script from a cloud object-storage URL via bash, which is a strong supply-chain risk and provides no visible integrity verification. The use of a less-established mirror endpoint further increases the trust burden and attack surface.
npx clawhub@latest install wangyan-gemini-image-gen
curl -fsSL https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/install/install.sh | bash -s -- --no-skills skillhub install wangyan-gemini-image-gen
Allowing arbitrary --base-url provider selection means the skill can be pointed at any external endpoint, including untrusted or attacker-controlled services, while sending API keys, prompts, and input images. In an image-editing skill, this context makes the issue more dangerous because user-supplied images may contain sensitive personal or business data.
uv run {baseDir}/scripts/generate_image.py --prompt "描述" --filename "output.png" \
--base-url "https://example.com/v1" --api-key "sk-xxx" --model "gemini-3.1-flash-image-preview"
The credential-access finding is substantiated because the script defines logic to enumerate and parse multiple .env files, including global and workspace scopes. In this skill context, that behavior can pull in secrets unrelated to the current task and make them available to subsequent network operations.
# 检查 uv 是否存在
check_uv()
# 加载 .env 文件(在导入其他模块之前)
def load_env_files(verbose: bool = False) -> list[Path]:
"""
从多个位置加载 .env 文件,优先级从低到高:
This line documents the multi-scope .env loading behavior that expands credential reach beyond the immediate skill directory. In an agent environment, broad secret discovery materially increases the chance of unintended credential use or leakage.
# 加载 .env 文件(在导入其他模块之前)
def load_env_files(verbose: bool = False) -> list[Path]:
"""
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
The declared loading of ~/.openclaw/.env shows the skill is intended to read global user-level configuration, which may contain unrelated secrets. That broadens the blast radius if the skill is invoked in a shared or multi-purpose environment.
def load_env_files(verbose: bool = False) -> list[Path]:
"""
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
Reading a skill-local .env is a common and generally acceptable way to supply configuration. Unlike the global/workspace .env behavior, this source is task-adjacent and does not by itself imply excessive credential access.
"""
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从多个位置加载 .env 文件,优先级从低到高:
1. /workspace/.env (沙箱环境)
2. ~/.openclaw/.env (全局配置)
3. 技能目录下的 .env (技能本地配置)
返回实际加载的 .env 文件路径列表
"""
Referencing /workspace/.env explicitly causes the skill to inspect a workspace-wide secret store, which may include credentials unrelated to this skill. In an agent runtime, that violates least-privilege expectations and can enable unintended secret consumption.
env_paths: list[Path] = []
loaded_paths: list[Path] = []
# 1. 沙箱环境 /workspace/.env
sandbox_env = Path("/workspace/.env")
if sandbox_env.exists():
env_paths.append(sandbox_env)
The existence check on /workspace/.env is part of the unauthorized credential discovery path. Even passive discovery of workspace secrets is risky when followed by automatic loading into process environment.
loaded_paths: list[Path] = []
# 1. 沙箱环境 /workspace/.env
sandbox_env = Path("/workspace/.env")
if sandbox_env.exists():
env_paths.append(sandbox_env)
The code targets ~/.openclaw/.env, a user-global configuration location that can hold sensitive credentials for unrelated tasks. Accessing it by default broadens credential exposure and can cause accidental cross-task secret reuse.
if sandbox_env.exists():
env_paths.append(sandbox_env)
# 2. 全局配置 ~/.openclaw/.env
home = Path.home()
global_env = home / ".openclaw" / ".env"
if global_env.exists():
No suspicious patterns detected.