T09 · Insecure Skill Coding Practices
- Location
scripts/sticker.py:38- Finding
HTTPS Requests Fall Back to Disabled Certificate Verification
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This sticker-sending skill is coherent in purpose, but its helper script has unsafe file and network handling that could write or delete files outside its sticker folder and fetch untrusted URLs.
Review this before installing. Use it only if you are comfortable with a chat skill that can fetch online media, store files locally, and send media through messaging channels. Avoid using arbitrary download URLs or user-supplied sticker names until filename containment, URL allowlisting, TLS verification, size/type checks, and confirmation before external sends/removals are added.
scripts/sticker.py:38HTTPS Requests Fall Back to Disabled Certificate Verification
scripts/sticker.py:142Unrestricted URL Download Enables Server-Side Request Forgery
scripts/sticker.py:116Unsanitized Sticker Names Permit Path Traversal and Arbitrary File Creation
scripts/sticker.py:200Untrusted Index Paths Permit Arbitrary File Deletion
scripts/sticker.py:157Unbounded Response Buffering Enables Memory and Disk Exhaustion
scripts/sticker.py:86Hardcoded Tenor API Key Exposes a Reusable Service Credential
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
url = f"https://tenor.googleapis.com/v2/search?{params}"
try:
req = urllib.request.Request(url, headers={"User-Agent": "OpenClaw-Sticker/1.0"})
with urllib.request.urlopen(req, timeout=10, context=_ssl_context()) as resp:
data = json.loads(resp.read())
results = []
for item in data.get("results", []):
The download command fetches an arbitrary user-supplied URL and writes the response body directly to disk. In the context of a chat assistant skill, this creates an SSRF-style network primitive and untrusted file ingestion path, which becomes more dangerous because TLS verification may be disabled by the custom SSL fallback.
try:
req = urllib.request.Request(url, headers={"User-Agent": "OpenClaw-Sticker/1.0"})
with urllib.request.urlopen(req, timeout=15, context=_ssl_context()) as resp:
dest_file.write_bytes(resp.read())
except Exception as e:
print(f"Download failed: {e}", file=sys.stderr)
The skill description emphasizes sending stickers in chat, but the documented behavior also includes local file management, remote downloading, and metadata storage that are not clearly declared as sensitive capabilities. This mismatch can mislead reviewers and users about what the skill will actually do, increasing the chance that file-system changes or network retrieval happen without informed consent.
If certificate discovery fails, the code explicitly disables hostname and certificate verification for all HTTPS requests. This permits man-in-the-middle attacks against sticker search and download traffic, allowing tampering with responses and substitution of malicious or unexpected content.
Online searches and downloads can silently proceed with TLS verification disabled, giving users no indication that transport security has been weakened. In a skill that retrieves remote media, this materially increases exposure to interception and content tampering.
The README states that the skill 'falls back to Tenor's massive library' but does not warn that search terms, emotional descriptors, or other user-derived queries may be sent to an external online service. This creates a privacy and transparency issue because users may reasonably assume sticker lookup is local-only unless outbound data sharing is disclosed.
The README advertises cross-channel operation on WhatsApp, Telegram, Discord, iMessage, and more, and describes the agent as sending stickers automatically, but it does not warn that content will be posted to third-party messaging platforms. In this context, lack of disclosure and approval guidance can lead to accidental external posting, privacy leakage, or reputational harm.
The README encourages users to invoke the skill through broad natural-language requests like 'send me a happy sticker' or 'react with a thumbs up gif' without clarifying approval boundaries, channel constraints, or confirmation requirements before sending. In a messaging skill that can post across external platforms, overly broad activation guidance increases the risk of unintended outbound actions from ambiguous conversational context.
The skill advertises and instructs operations that imply network access, local file reads/writes, and environment-variable use, but it declares no explicit tool scope or permissions. That makes the effective capability boundary unclear and increases the risk of over-privileged execution or accidental access to local files and remote content without appropriate review.
The trigger text is broad enough to match common conversational phrases like wanting to send a meme or sticker, which can cause the skill to activate in situations where the user did not intend file download or message transmission. In a skill that can fetch remote content and send media externally, ambiguous activation materially raises the risk of unintended actions.
The skill instructs downloading remote media and sending it through external chat channels but provides no explicit warning about the privacy, safety, or consent implications. Users may not realize that remote content will be fetched, stored locally, and then transmitted to third parties, which creates risks around malicious files, sensitive metadata, and unintended disclosure.
The workflow example starts from very general user language and proceeds directly into search and send actions without clear invocation constraints. Because the skill handles both local files and online content, this ambiguity can lead to automatic execution when the user may only be asking casually rather than authorizing retrieval and transmission.
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.
def _ssl_context():
"""Create an SSL context with robust cert discovery for macOS."""
cert_paths = [
os.environ.get("SSL_CERT_FILE", ""),
"/private/etc/ssl/cert.pem",
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.
except Exception:
continue
# Last resort: skip verification
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
dest_file = STICKER_DIR / f"{dest_name}_{counter}{src.suffix}"
counter += 1
shutil.copy2(str(src), str(dest_file))
index = load_index()
entry = {
The remove command unlinks the sticker file from disk and rewrites the index, which is an irreversible local data modification. The code prints a message after deletion, but there is no confirmation prompt, pre-action warning, or inline documentation warning users that files will be deleted.
The instruction to auto-detect the channel from conversation context encourages sending media to an external destination without explicit user opt-in at send time. In a messaging context, even a correct guess can result in accidental disclosure to the wrong platform or recipient, making automation risky.
No suspicious patterns detected.