Back to skill

Security audit

Vitamin Tracker Channel

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed vitamin reminder scheduler that creates channel cron reminders from a local schedule file, with normal caution around persistent reminders and trusted schedule contents.

Install only if you want this skill to manage persistent vitamin reminder cron jobs for the configured Discord channel. Keep VITAMINS.md writable only by trusted users, review schedule text before syncing, and remember that running the script changes OpenClaw cron state.

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
scripts/update_vitamin_crons.py:67
Finding

Persistent Indirect Prompt Injection Through Untrusted Reminder Content

Content
View full analysis

Vulnerability Details

File Location: scripts/update_vitamin_crons.py, lines 67–84
Vulnerability Type: Persistent indirect prompt injection caused by embedding untrusted file content in an agent instruction
Risk Level: Medium

Vulnerable Code

python
def ensure_job(label, hhmm, items, channel_id):
    slug = label.lower().replace(' ', '-')
    name = f'vitamins-{slug}-reminder'
    expr = time_to_cron(hhmm)
    reminder_text = build_message(label, items)
    session_key = SESSION_KEY_TEMPLATE.format(channel_id=channel_id)
    return run_openclaw([
        'add',
        '--name', name,
        '--session-key', session_key,
        '--cron', expr,
        '--tz', TZ,
        '--message', f'Send a brief reminder to the user in the bound session: "{reminder_text}"',
        '--timeout-seconds', '120',
        '--announce',
        '--channel', 'discord',
        '--to', channel_id,
        '--json',
    ])

Technical Analysis

The label and items values originate from the user-controlled $WORKSPACE/VITAMINS.md file. build_message() combines these values into reminder_text, which is then embedded verbatim in the --message argument supplied to an OpenClaw cron job.

Although reminder_text is surrounded by quotation marks, quotation marks do not create a security boundary in a natural-language agent prompt. A malicious label or supplement entry can contain instructions directing the receiving agent to ignore the intended reminder task and perform unrelated actions. The resulting instruction is stored as a cron job and is delivered repeatedly to the bound Discord agent session.

This is not operating-system shell injection because subprocess.run() receives an argument list and does not enable a shell. The vulnerability instead occurs at the agent instruction boundary: attacker-controlled data and trusted operational instructions are combined in the same natural-lang ...[truncated 1919 chars]

Remediation
View remediation

Remediation Suggestions

  1. Avoid invoking an agent for literal reminders. Prefer a cron delivery mechanism that posts a fixed, literal message directly to the destination without asking a language model or autonomous agent to interpret it.

  2. Separate instructions from untrusted data. If agent execution is unavoidable, transmit labels and supplement items through typed or structured fields and configure the receiving component to treat those fields exclusively as data.

  3. Apply strict input validation.

    • Restrict labels to a conservative character allowlist.
    • Restrict supplement names to expected printable characters.
    • Reject line breaks, control characters, quotation-based prompt delimiters, and instruction-like structural content.
    • Enforce reasonable length limits on labels, individual items, and the complete reminder.
    • Validate schedule times as real values from 00:00 through 23:59.
  4. Use an explicit non-execution template. If natural-language delivery remains necessary, state that the enclosed content is untrusted display data and must not be interpreted as instructions. This is defense in depth and should not replace direct literal delivery or structural isolation.

  5. Constrain the cron agent. Bind reminder jobs to an identity with no file, shell, administrative, secret-access, or unrelated messaging capabilities. Limit it to posting in the explicitly configured destination.

  6. Protect the input file. Apply restrictive filesystem permissions to $WORKSPACE/VITAMINS.md and its parent directory so that only the intended account can modify the schedule.

  7. Review generated jobs before activation. Display the final message and require confirmation when content contains unexpected punctuation, excessive length, multiline text, or instruction-like phrases.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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 (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill performs security-relevant actions via environment variables, workspace file reads, and shell execution (python3 and openclaw cron) but does not declare any explicit tool scope such as permissions or allowed-tools. This creates a least-privilege gap: the runtime may permit broader tool access than users or reviewers expect, making it easier for a modified or compromised script to read unintended files or execute additional commands.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/update_vitamin_crons.py (reported line 72)May include surrounding context.

python
def run_openclaw(args):
    cmd = ['openclaw', 'cron'] + args
    return subprocess.run(cmd, capture_output=True, text=True, check=False)


def ensure_job(label, hhmm, items, channel_id):

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script unconditionally removes and recreates scheduled jobs based on VITAMINS.md without confirmation, dry-run output, or change review. In this skill context, that can silently alter reminder timing or destination for a live Discord channel, causing integrity issues and accidental disruption of user-facing automations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The code accesses VITAMIN_CHANNEL_ID from the environment and uses it to target reminders, but provides no comment or warning that environment-provided configuration is being consumed. Under this rule, access to environment-based identifiers or credentials should have some disclosure unless clearly documented as part of the skill's stated purpose.

Content

No source excerpt is available for this finding.