Back to skill

Security audit

QuotLy Style Sticker

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its sticker-making purpose, but it sends chat content and profile details to a remote renderer and has under-scoped network protections that need review.

Review before installing in sensitive chat or cloud-hosted environments. Only use it when users understand that selected message content and sender/profile fields may be sent to the configured QuotLy rendering service, set QUOTLY_API_ALLOW_HOSTS to the intended host, and avoid using it where the process can reach internal services until redirect and DNS-rebinding protections are tightened.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/openclaw_quote_autoreply.py:46
Finding

SSRF Protection Can Be Bypassed Through Unvalidated Redirects and DNS Rebinding

Content
View full analysis
str: """Sanitize API URL to prevent SSRF attacks.""" parsed = urllib.parse.urlparse(url) if parsed.scheme.lower() not in ("http", "https"): raise ValueError(f"API URL must use HTTP or HTTPS scheme: {url}") host = (parsed.hostname or "").lower().rstrip(".") if not host: raise ValueError("API URL must have a valid hostname") # First check: hostname string validation if _is_disallowed_host(host): raise ValueError(f"API URL points to disallowed host: {host}") # Second check: DNS rebinding protection - resolve and validate IP _resolve_and_validate_host(host) # Third check: path traversal prevention path = urllib.parse.unquote(parsed.path or "/") if ".." in path or "//" in path.replace("//", "/"): raise ValueError(f"API URL contains suspicious path traversal: {path}") # Check against allowlist if configured allow_hosts = os.getenv("QUOTLY_API_ALLOW_HOSTS", "") if allow_hosts: allowed = {h.strip().lower().rstrip(".") for h in allow_hosts.split(",") if h.strip()} if host not in allowed: raise ValueError(f"API URL host not in allowlist: {host}") return parsed._replace(fragment="", username=None, password=None).geturl() ``` ```python def _request_quote_api_bytes( api_url: str, payload: Dict[str, Any], timeout_seconds: float ) -> bytes: # Enforce max payload size (1MB) payload_bytes = json.dumps(payload).encode("utf-8") max_payload_size = 1024 * 1024 if len(payload_bytes) > max_payload_size: raise ValueError(f"Payload exceeds maximum size of {max_payload_size} bytes") request = urllib.request.Request( ...[truncated 4165 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · scripts/openclaw_quote_autoreply.py (reported line 28)May include surrounding context.

python
return True
    if lowered.endswith(".local") or lowered.endswith(".internal"):
        return True
    if lowered in ("metadata.google.internal", "169.254.169.254"):
        return True

    try:

Cloud Metadata Access

High
Category
Server-Side Request Forgery
Confidence
90% confidence
Finding

Code accesses a cloud instance metadata endpoint (e.g. 169.254.169.254). A single request can return temporary IAM credentials, making this a high-value SSRF target for credential theft.

Content

Scanner excerpt · scripts/openclaw_quote_autoreply.py (reported line 28)May include surrounding context.

python
return True
    if lowered.endswith(".local") or lowered.endswith(".internal"):
        return True
    if lowered in ("metadata.google.internal", "169.254.169.254"):
        return True

    try:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes a local Python script and, by its own documentation, uses environment variables, reads input, writes media files, and makes outbound network requests, yet it declares no explicit tool scope or permission boundaries. This creates an over-privileged integration surface where an agent/runtime may allow broader capabilities than intended, increasing the risk of data exfiltration, unsafe file access, or unreviewed network usage.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The default prompt uses a broad natural-language activation pattern ('Use $quotly-style-sticker to generate quote stickers...') combined with implicit invocation, but it does not clearly constrain who can trigger it or require strict validation that the referenced messages were intentionally selected for processing. In a messaging context, this can cause the skill to activate on loosely matched requests and process forwarded or quoted content unexpectedly, which may expose message text or profile metadata to the downstream sticker-generation tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script sends selected message text, inferred formatting entities, and forwarded-profile fields such as display name and avatar URL to a third-party QuotLy API. In a messaging skill that processes forwarded or quoted messages, this can expose potentially sensitive user content and metadata off-platform without any explicit consent gate, notice, or hard trust boundary, creating a real privacy and data-handling risk even if the transmission is over HTTPS.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This JSON sample embeds a specific non-default locale representation in natural-language content via the name fields "张" and "三". Because SQP-3 applies to all file types and there is no surrounding note that the skill is region-specific or that language/locale is user-selectable, this can be read as a locale-specific assumption in sample behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.