T09 · Insecure Skill Coding Practices
- Location
emoji_sender.py:47- Finding
Unvalidated Remote Image URL Enables Server-Side Request Forgery
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is coherent for sending Feishu emoji images, but it needs review because it downloads unvalidated third-party media into OpenClaw storage and can send it to chats.
Install only if you are comfortable with the agent contacting fabiaoqing.com and related image CDNs, saving downloaded files into OpenClaw's media directory, and sending those files in Feishu chats. Prefer explicit user requests, restrict allowed image hosts, add media size/type validation, sanitize filenames, and avoid automatically executing tool-call text printed by the helper script.
emoji_sender.py:47Unvalidated Remote Image URL Enables Server-Side Request Forgery
emoji_sender.py:69Unbounded Remote Download Can Exhaust Memory and Persistent Storage
emoji_sender.py:89User-Controlled Text Is Embedded in an Executable-Looking Agent Tool Call
The skill directs the agent to fetch attacker-controlled or third-party remote content with curl and write it into a trusted local media directory, then immediately send it onward. This creates SSRF-like and content-trust risks: unvalidated URLs can cause unexpected outbound network access, persistence of untrusted files on disk, and redistribution of malicious or inappropriate content without user awareness or approval.
The image URL is derived from untrusted remote HTML and then fetched directly with requests.get, creating an SSRF-style primitive and allowing the script to contact attacker-controlled hosts. In this skill's context, the risk is increased because the fetched content is then written into a local media directory, so an attacker controlling the search result page or image URL could trigger unexpected outbound requests and store arbitrary remote content locally.
headers = {"Referer": REFERER}
try:
resp = requests.get(img_url, headers=headers, timeout=10)
resp.raise_for_status()
with open(filepath, 'wb') as f:
The destination path is influenced by an environment variable and the filename incorporates unsanitized user-controlled keyword data, so the script can write files outside the intended media area via path manipulation such as '../'. In this context, the risk is more than theoretical because the tool is explicitly designed to save files locally, and an attacker who can control the keyword or environment could overwrite or create arbitrary files accessible to the running user.
resp = requests.get(img_url, headers=headers, timeout=10)
resp.raise_for_status()
with open(filepath, 'wb') as f:
f.write(resp.content)
return filepath
The natural-language description is presented only in Chinese and frames the skill around Chinese-language usage, while the manifest provides no opt-in or alternative language/locale handling. Under the stated policy, forcing a specific language without user choice can be a locale-policy violation.
The manifest defines very broad trigger keywords such as common acknowledgements, emotions, and workplace terms that overlap heavily with normal conversation. In an agent skill context, this can cause unintended activation and automatic sending of external media in response to routine speech, creating spam, confusing behavior, and possible misuse of messaging actions without clear user intent.
The file presents all operational instructions, warnings, and examples in Chinese only. Under the stated policy, forcing a specific language without giving the user a choice can be a natural-language policy violation unless the locale restriction is explicitly justified.
This Python file contains natural-language documentation entirely in Chinese, including usage examples, without any indication that the user can choose another language or that the skill is region-specific. Under the policy for natural-language violations, forcing a specific language without user opt-in is a reportable issue.
No suspicious patterns detected.