T09 · Insecure Skill Coding Practices
- Location
scripts/qwen_image.py:409- Finding
Arbitrary API Endpoint Can Receive DashScope Credentials and Private Image Data
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill performs the promised image generation, but it can send your API key, prompts, and selected images to a configurable endpoint and downloads unvalidated response URLs.
Install only if you trust the publisher and will run it in a controlled directory. Avoid untrusted project folders with .env files, do not set DASHSCOPE_ENDPOINT unless you control and trust that server, and assume prompts plus selected input images are uploaded to the configured endpoint and saved locally afterward.
scripts/qwen_image.py:409Arbitrary API Endpoint Can Receive DashScope Credentials and Private Image Data
scripts/qwen_image.py:166Unvalidated Response URLs Permit SSRF and Unbounded Content Downloads
requirements.txt:1Unpinned Dependencies Reduce Build Integrity and Reproducibility
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
if size:
payload["parameters"]["size"] = size
response = requests.post(
endpoint,
headers={
"Authorization": f"Bearer {api_key}",
The declared purpose frames the skill narrowly as image generation/editing, but the instructions and referenced behavior include additional capabilities: fetching arbitrary URLs, downloading and republishing files, creating HTML viewer pages, loading .env configuration, and emitting channel-specific payload conventions. This mismatch increases the chance that reviewers or users underappreciate the skill's data movement and persistence behavior, which can enable SSRF-like fetching, unintended publication of content, or exposure of local deployment details.
Referenced artifact was not completely inspected
- First use `read` on this `SKILL.md`, then execute the Python command below.
Referenced artifact was not completely inspected
- First use `read` on this `SKILL.md`, then execute the Python command below.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Or use .env (auto-loaded from current directory, then {baseDir}):
cat > .env <<'EOF'
DASHSCOPE_API_KEY=your_api_key
DASHSCOPE_REGION=sg
OPENCLAW_MEDIA_OUTBOUND_DIR=~/.openclaw/media/outbound
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Or use `.env` (auto-loaded from current directory, then `{baseDir}`):
```bash
cat > .env <<'EOF'
DASHSCOPE_API_KEY=your_api_key
DASHSCOPE_REGION=sg
OPENCLAW_MEDIA_OUTBOUND_DIR=~/.openclaw/media/outbound
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Or use `.env` (auto-loaded from current directory, then `{baseDir}`):
```bash
cat > .env <<'EOF'
DASHSCOPE_API_KEY=your_api_key
DASHSCOPE_REGION=sg
OPENCLAW_MEDIA_OUTBOUND_DIR=~/.openclaw/media/outbound
The script automatically reads .env from the current working directory, which is less trusted than the application directory and can enable environment poisoning if the tool is run inside an attacker-controlled folder. An attacker could supply a malicious .env to redirect endpoints or swap credentials, causing unintended data egress or account misuse.
def resolve_dotenv_paths() -> list[Path]:
candidates = [
Path.cwd() / ".env",
Path(__file__).resolve().parent.parent / ".env",
]
dedup = []
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def resolve_dotenv_paths() -> list[Path]:
candidates = [
Path.cwd() / ".env",
Path(__file__).resolve().parent.parent / ".env",
]
dedup = []
seen = set()
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def resolve_dotenv_paths() -> list[Path]:
candidates = [
Path.cwd() / ".env",
Path(__file__).resolve().parent.parent / ".env",
]
dedup = []
seen = set()
The skill exposes capabilities consistent with environment access, file read/write, and network use, but does not declare any explicit tool scope or allowed-tools boundary. In a skill system, this weakens reviewability and enforcement, making it easier for the skill to perform side effects the caller may not expect, especially when combined with external API calls and filesystem publishing.
The instructions require that failures be reported in exactly two short Chinese sentences. This forces a specific language regardless of the user's language preference, and the file does not offer any opt-in, fallback, or region-specific justification for the constraint.
The script transmits user prompts and possibly image content to an external service. While this is core functionality, it is still a real data egress path and becomes security-relevant because the skill also supports local-file ingestion and optional endpoint override, which can increase the chance of sensitive data leaving the host unexpectedly.
if size:
payload["parameters"]["size"] = size
response = requests.post(
endpoint,
headers={
"Authorization": f"Bearer {api_key}",
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
parser.add_argument("--n", type=int, default=1, help="number of output images, range [1,6]")
parser.add_argument("--size", default="", help='optional size like "1024*1024"')
parser.add_argument("--negative-prompt", default=" ", help="negative prompt")
parser.add_argument("--no-prompt-extend", action="store_true", help="disable prompt extension")
parser.add_argument("--watermark", action="store_true", help="enable output watermark")
parser.add_argument("--out-dir", default="./tmp/qwen-image", help="directory to save downloaded images")
parser.add_argument(
Several reply strings and help text explicitly specify or emit Chinese output such as 'Chinese text + markdown image URL' and '已为你生成图片。' regardless of user preference. This forces a specific language in natural-language output without any opt-in or locale selection mechanism.
The script sends prompts and, in img2img mode, user-supplied images to a third-party remote API without any explicit runtime disclosure or consent mechanism. In a skill context, users may assume local processing, so silent external transmission can expose sensitive images or prompt content to the provider.
The dependency specifier requests>=2.31.0 is unpinned, so builds may resolve to different versions over time and can inadvertently pick up a vulnerable or breaking release. In a skill that likely performs network access, this weakens supply-chain reproducibility and makes it harder to verify whether a safe version is installed.
requests>=2.31.0
Pillow>=10.0.0
requests has multiple known advisories, and because the manifest does not pin an exact version, it is impossible to determine from this file alone whether an affected release will be installed. In a network-enabled skill, that uncertainty increases risk because dependency resolution may select a vulnerable version in some environments.
The dependency specifier Pillow>=10.0.0 is unpinned, which means installations are not reproducible and may drift to versions with new vulnerabilities or incompatible behavior. Because this skill handles image generation or editing, Pillow is security-relevant and malformed-image attack surface makes version control important.
requests>=2.31.0
Pillow>=10.0.0
Pillow has a history of security advisories, and the unpinned requirement prevents verification that deployments will use a non-vulnerable release. Since this skill processes images, any vulnerable image-parsing library is especially relevant due to risks such as denial of service or potentially worse parser flaws.
The script automatically downloads and republishes generated images into local output and outbound publish directories, potentially creating persistent artifacts without clear disclosure. In shared or multi-user environments, this can unintentionally retain or expose generated content longer than expected.
No suspicious patterns detected.