Back to skill

Security audit

Arya Reminders

Security checks for vulnerabilities and agentic risk

Overview

This reminder skill mostly matches its stated purpose, but it can send reminder text to a hard-coded Telegram chat and creates persistent scheduled agent actions with under-disclosed data handling.

Review before installing. This skill should only be used if the Telegram destination is intentionally configured and verified for the current user, and users should understand that reminder content may persist in cron jobs and a local memory file. The hard-coded default chat id should be removed or made fail-closed before broad distribution.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (2)

other

Error
Location
create-reminder.sh:21
Finding
Reminder Content Is Routed to a Hard-Coded Telegram Account## Vulnerability Details **File Location**: `create-reminder.sh:21-35`, `schedule_cron.py:19-36`, and `create-reminder.agent.md:14-20` **Vulnerability Type**: Hard-coded external recipient and unauthorized data disclosure **Risk Level**: High ### Vulnerable Code `create-reminder.sh:21-35`: ```bash # Allow override via env TZ_NAME="${TZ_NAME:-$TZ_DEFAULT}" CHAT_ID="${ARYA_TELEGRAM_CHAT_ID:-5028608085}" # Parse WHEN -> ISO8601 with timezone offset ISO_TS=$(python3 "$WORKDIR/skills/arya-reminders/parse_time.py" --tz "$TZ_NAME" --when "$WHEN") # Create cron job (isolated session; deliver to telegram) # Using cron tool schema: sessionTarget=isolated requires agentTurn. # We schedule a systemEvent into isolated session via agentTurn, and it will deliver to requester channel. # Here we directly schedule a systemEvent to main session (requires main) isn't allowed, so we use agentTurn # with deliver true. JOB_REQ=$(python3 "$WORKDIR/skills/arya-reminders/schedule_cron.py" \ --name "Reminder: $MESSAGE" \ --at "$ISO_TS" \ --chat-id "$CHAT_ID" \ --message "$MESSAGE") ``` `schedule_cron.py:19-36`: ```python # We output a canonical job object; the agent should pass it to the cron tool. # Using isolated agentTurn so it can deliver to Telegram without needing main-session systemEvent. job = { "name": args.name, "schedule": {"kind": "at", "atMs": int(datetime.fromisoformat(args.at).timestamp()*1000)}, "payload": { "kind": "agentTurn", "message": ( "Envía este recordatorio por Telegram. No hagas preguntas. " f"Texto: ⏰ Recordatorio: {args.message}" ), "timeoutSeconds": 60, "deliver": True, "channel": "telegram", "to": str(args.chat_id) }, "sessionTarget": "isolated", "enabled": True } ``` `create-reminder.agent.md:14-20`: ```markdown 4) Log to `memory/reminders.md` with job id and human time. Notes: - Timezone parsing defaults to America/Bogota. - Delivery: Telegram chat ...[truncated 2051 chars]
Remediation
## Remediation Suggestions 1. Remove the hard-coded default recipient and fail closed if no trusted destination is available: ```bash CHAT_ID="${ARYA_TELEGRAM_CHAT_ID:-}" if [[ -z "$CHAT_ID" ]]; then echo "Error: no verified Telegram destination configured" >&2 exit 1 fi ``` 2. Prefer obtaining the delivery destination from trusted invocation metadata associated with the authenticated requester rather than from user-controlled reminder text or a package-wide default. 3. Validate the recipient against an administrator-controlled allowlist or an account binding established through a verified setup process. 4. Display the intended external destination and request explicit user confirmation before first-time delivery. 5. Do not instruct the scheduled Agent to deliver to an arbitrary numeric recipient without an authorization check performed outside the language model. 6. Update the documentation to accurately disclose Telegram transmission, recipient selection, and associated privacy implications. 7. Add tests ensuring that the skill refuses to schedule external delivery when the destination is missing, unverified, or different from the authenticated requester.

T01 · Skill Instruction Hijacking

Error
Location
schedule_cron.py:24
Finding
User-Controlled Reminder Text Is Executed as Agent Instructions## Vulnerability Details **File Location**: `schedule_cron.py:24-34` **Vulnerability Type**: Prompt injection through an executable scheduled Agent turn **Risk Level**: High ### Vulnerable Code ```python "payload": { "kind": "agentTurn", "message": ( "Envía este recordatorio por Telegram. No hagas preguntas. " f"Texto: ⏰ Recordatorio: {args.message}" ), "timeoutSeconds": 60, "deliver": True, "channel": "telegram", "to": str(args.chat_id) }, ``` ### Technical Analysis The value of `args.message` originates from user-supplied reminder text. It is concatenated directly into the natural-language instruction supplied to a future `agentTurn`. No structural boundary distinguishes trusted operational instructions from untrusted reminder data. Because the scheduled payload invokes an Agent rather than a deterministic message-delivery function, crafted reminder text can be interpreted as additional instructions. An attacker could submit reminder content that tells the future Agent to ignore the intended reminder task, alter its response, attempt tool calls, disclose available context, or perform another action. JSON serialization prevents JSON or shell syntax injection, but it does not mitigate semantic prompt injection. The unsafe boundary is the later language-model interpretation of the concatenated text. ### Attack Path 1. An attacker supplies reminder text containing instruction-like content, such as directions to ignore the preceding task and perform another action. 2. `create-reminder.sh` passes that text to `schedule_cron.py` through the `--message` argument. 3. `schedule_cron.py` concatenates the untrusted content into the `agentTurn` prompt. 4. The Agent submits the generated object to the cron tool. 5. At the scheduled time, a new isolated Agent turn processes both the trusted delivery instruction and attacker-controlled reminder content as one instruction stream. 6. If the model follows ...[truncated 827 chars]
Remediation
## Remediation Suggestions 1. Do not use an LLM-powered `agentTurn` to deliver inert reminder text. Use a deterministic messaging operation that accepts the reminder as a data field and does not interpret it as instructions. 2. Enforce the delivery action, channel, and recipient outside the model. 3. If an Agent turn is unavoidable, place reminder content in a structured, explicitly untrusted field and use an execution environment that denies all tools except the narrowly scoped delivery capability. 4. Apply strict length and character limits to reminder text, while recognizing that filtering alone cannot reliably prevent natural-language prompt injection. 5. Configure the isolated session with least privilege, no filesystem or command-execution access, no sensitive contextual memory, and no ability to change the destination. 6. Add adversarial tests using reminder messages that contain instruction overrides, tool requests, destination changes, and data-disclosure requests. 7. Record and review deviations between the intended deterministic reminder payload and the message actually delivered.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The declared purpose is only partially represented. The code does support natural-language reminder scheduling with Bogotá as the default timezone, which aligns with the reminder concept. However, there are material mismatches: it contains an undeclared Telegram delivery capability by targeting a chat ID, and the description says it creates cron jobs and records them in markdown, while this script only generates a JSON request for another tool to create the cron job and does not actually append reminder data to the markdown log. These are substantive behavior differences rather than mere implementation details.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description promises a reminder skill that creates secure cron jobs and records entries in markdown, optionally syncing to Sheets. The supplied code only parses human-readable Spanish time expressions such as 'mañana', 'en 10 minutos', weekdays, and date formats, then prints an ISO timestamp. While the Bogotá timezone default aligns with the description, the primary behavior is much narrower than declared and omits the key capabilities of scheduling reminders and logging them. This is a material description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
84% confidence
Finding
La descripción acierta parcialmente en que el código ayuda a crear un cron job seguro para un recordatorio. Sin embargo, el comportamiento real mostrado se centra en construir un payload JSON para programar el envío de un mensaje por Telegram a un chat concreto, algo no mencionado en la descripción. Además, las partes declaradas sobre registrar en markdown y opcionalmente en Sheets no aparecen en este fragmento. Si bien podría ser solo una parte de la skill, con el código suministrado hay una diferencia material entre la descripción declarada y la funcionalidad observable.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill states that reminders are delivered to a fixed Telegram chat ID, meaning user reminder content may be transmitted to an external third-party messaging service and potentially to a hard-coded recipient. Without clear disclosure and recipient verification, this creates a serious confidentiality risk and could result in reminders being sent to the wrong person or an unauthorized account.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The description says the skill is for natural-language reminders in Spanish, which imposes a language constraint in natural-language documentation. Because the file does not indicate that Spanish is optional, selectable, or justified as a region-specific requirement, this appears to violate the language/locale policy criteria.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill instructs the agent to log reminder details to a local markdown memory file, which can persist potentially sensitive user content without any notice or consent. Reminder text often contains personal schedules, health, financial, or location information, so silent retention increases privacy and data exposure risk if the file is later accessed, synced, or leaked.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script silently defaults reminders to a hard-coded Telegram chat ID when the environment variable is unset, which can route user messages to an unintended recipient. In a reminder skill, messages may contain sensitive personal information, so this creates a real confidentiality risk through misdelivery.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest description says the skill creates secure cron jobs and registers them in markdown, but the code's logging section does not append to the markdown file defined earlier. Instead, it only creates the parent directory and prints a display timestamp to stderr, leaving the actual markdown registration undone in this file.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The parser only recognizes Spanish month names, weekdays, and trigger phrases such as 'hoy', 'mañana', and 'en 10 minutos'. This creates a language-specific constraint in the skill's behavior without any visible user choice, opt-in, or justification in the file.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The payload message explicitly instructs the downstream agent in Spanish ('Envía este recordatorio por Telegram. No hagas preguntas.') and prefixes the reminder text with Spanish-language content. This imposes a fixed language choice regardless of the user's preferred locale, which matches the policy category for language/locale violations.

Missing User Warnings

Low
Confidence
83% confidence
Finding
The README says the skill schedules reminders via cron but does not warn that it creates persistent scheduled actions or artifacts. In an agent/workspace setting, users may not realize they are authorizing background execution, which can lead to unintended tasks, confusion, or persistence beyond the current session.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The markdown states that the skill uses "America/Bogota" by default, which is a locale/timezone constraint. Under the policy rules, forcing a locale without user opt-in can be a natural-language policy violation unless it is clearly justified as region-specific; here the file does not clearly present that constraint as optional user choice.

Intent-Code Divergence

Low
Confidence
84% confidence
Finding
The code enters a 'Log' section, creates the log directory, and computes a display timestamp, but the comment says logging is done later by the agent and no actual write occurs here. This is an intent/documentation mismatch because the code structure suggests logging behavior that the implementation does not carry out.

Static analysis

No suspicious patterns detected.