Back to skill

Security audit

WastePickupReminder

Security checks for vulnerabilities and agentic risk

Overview

This waste-reminder skill is mostly coherent, but it stores sensitive messaging targets and uses unescaped cron output that could misroute automated messages if the config is influenced or malformed.

Review this before installing if the reminder config may be edited from shared workspaces or natural-language input. Protect the config directory, avoid committing config.json or schedule.json, treat Discord webhook URLs as secrets, and prefer a version that emits structured JSON or validates recipients and channels before automated sending.

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

Warning
Location
waste_cron.py:87
Finding
Unescaped Configuration Values Permit Output-Protocol Injection## Vulnerability Details **File Location**: `waste_cron.py`, lines 87–122 and 143–147 **Vulnerability Type**: Output-protocol injection through unvalidated configuration values **Risk Level**: Medium ### Vulnerable Code ```python # Build message template = reminder_config.get("template", "Reminder: {container_name}") container_emoji = container_info.get("emoji", "🗑️") container_name = container_info.get("name", container) message = template.replace("{container_emoji}", container_emoji) message = message.replace("{container_name}", container_name) message = message.replace("{date}", date) # Get recipient info target_key = reminder_config.get("target", "group_whatsapp") # Target name now includes channel (e.g., group_whatsapp, me_telegram) # Extract channel from target name if not specified in reminder_config target_info = get_target_info(targets, target_key) recipient_id = target_info.get("id") # Use channel from target info, or try to extract from target name channel = target_info.get("channel") if not channel: # Extract channel from target key (e.g., group_whatsapp -> whatsapp) if "_" in target_key: channel = target_key.split("_")[-1] else: channel = "whatsapp" if recipient_id: reminders_to_send.append({ "recipient": recipient_id, "channel": channel, "message": message, "container": container, "date": date, "time_slot": time_slot }) ``` ```python # Output for automation print(f"SEND_TO:{r['recipient']}") print(f"CHANNEL:{r['channel']}") print(r["message"]) print("---") ``` ### Technical Analysis The script uses a line-oriented protocol in which `SEND_TO:`, `CHANNEL:`, and `---` have structural meaning. Recipient identifiers, channel names, container metadata, and message templates are read from editable JSON configuration and emitted into this protocol without schema validation, ...[truncated 2661 chars]
Remediation
## Remediation Suggestions 1. Replace the ad hoc line-oriented output with strict JSON serialization. Emit one JSON object per reminder or a single JSON array, and require the consumer to parse it as data rather than executable routing text. ```python output = { "recipient": r["recipient"], "channel": r["channel"], "message": r["message"], "container": r["container"], "date": r["date"], "time_slot": r["time_slot"], } print(json.dumps(output, ensure_ascii=False)) ``` 2. Enforce a configuration schema before processing: - Allow only explicitly supported channels such as `whatsapp`, `telegram`, `discord`, and `email`. - Require recipient identifiers to match channel-specific formats. - Reject newline, carriage-return, null, and other control characters in routing fields. - Require templates and container metadata to be strings with reasonable length limits. 3. If the existing text protocol must be retained, encode every untrusted field using an unambiguous mechanism such as JSON string encoding or Base64. Do not rely only on replacing known marker strings. 4. Harden the downstream consumer so it accepts only a formally parsed record schema, rejects duplicate or unknown fields, validates recipients against an authorized allowlist, and never interprets protocol-like text inside the message field. 5. Restrict permissions on `config.json` and its containing directory so that only the intended service account can modify routing configuration. 6. Add tests covering templates and routing values containing `\n`, `\r`, `SEND_TO:`, `CHANNEL:`, and `---` to verify that they cannot create additional records or modify record boundaries.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill documentation explicitly instructs users to store contact identifiers, phone numbers, chat IDs, email addresses, and even Discord webhook URLs in local JSON configuration files, but it provides no privacy or security warning about the sensitivity of that data. If the workspace, backups, logs, or shared files are exposed, these identifiers and endpoints could be harvested for spam, phishing, unauthorized messaging, or webhook abuse.

Static analysis

No suspicious patterns detected.