Back to skill

Security audit

PomoClaw

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent PomoClaw timer controller, but it should be reviewed because it tells the agent to pass timer URLs through a shell command on a Mac.

Install only if you are comfortable with the agent running Mac-node commands to control PomoClaw. Timer durations and configuration values should be strictly limited to the documented numeric ranges and sound names, and malformed text should be rejected rather than placed into the shell command.

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
SKILL.md:16
Finding
Potential Shell Command Injection Through Dynamically Constructed URL Parameters<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 16–17 and line 74 **Vulnerability Type**: Shell command injection **Risk Level**: Medium ### Vulnerable Code Snippet ```markdown Run via `nodes.run` on the Mac node using `bash -c "open 'pomoclaw://...'"`: ``` ```markdown - Use `bash -c "open 'pomoclaw://...'"` via nodes.run (more reliable than array format with URL encoding) ``` The documented command patterns include dynamically supplied values, such as: ```text pomoclaw://start?minutes=N pomoclaw://break?minutes=N pomoclaw://config?sound=Glass ``` ### Technical Analysis The Skill explicitly directs the Agent to construct a URL containing request-derived parameters and pass it through `bash -c`. A shell is unnecessary for opening the URL and introduces an additional parsing layer. The URL is enclosed in single quotes, but the instructions do not require the Agent to validate every parameter according to an allowlist or escape values for shell use. If attacker-controlled text containing a single quote and shell operators is substituted into a URL parameter, it can terminate the quoted URL and add a second shell command. For example, unsafe interpolation of a crafted value conceptually resembling: ```text 25'; attacker_command; # ``` could produce a command structurally equivalent to: ```bash bash -c "open 'pomoclaw://start?minutes=25'; attacker_command; #'" ``` The shell would interpret `attacker_command` as a separate command rather than as part of the URL. The documented `1–99` timer range reduces the expected input domain, but the Skill does not explicitly instruct the Agent to parse the value as an integer and reject all nonnumeric input before constructing the shell command. Configuration values similarly require strict validation. ### Attack Path 1. An attacker submits a timer or configuration request containing a quote and shell metacharacters in a parameter value. 2. The Agent follows the Skill and interpolates tha ...[truncated 1213 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Remove `bash -c` from the invocation path.** Invoke `/usr/bin/open` directly through an argument-array execution API so that the URL is passed as one literal argument and is never parsed as shell syntax. For example, use the conceptual equivalent of: ```text executable: /usr/bin/open arguments: - pomoclaw://start?minutes=25 ``` 2. **Strictly validate numeric parameters.** - Parse timer durations as integers rather than strings. - Accept only values from `1` through `99`. - Reject signs, whitespace, decimal notation, shell metacharacters, and trailing text. - Apply documented bounds to configuration durations and completed-count values. 3. **Allowlist enumerated parameters.** - Accept sound names only from the documented sound list. - Accept Boolean settings only as exact canonical values such as `true` or `false`. - Reject unknown configuration keys. 4. **Encode URL components.** Construct the custom URL with a URL-component encoder after semantic validation. URL encoding is defense in depth and should not be treated as a substitute for avoiding shell execution. 5. **Add an explicit safety rule to the Skill.** State that raw user text must never be interpolated into a shell command and that malformed values must produce an error rather than being passed through. 6. **Add adversarial validation tests.** Test values containing quotes, semicolons, command substitutions, newlines, redirection operators, and URL delimiters to verify that they are rejected before any node command is issued. ]]>
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Session Persistence

Medium
Category
Rogue Agent
Content
pomoclaw://start?minutes=N           # Start timer for N minutes (1-99)
pomoclaw://pause                     # Pause/resume toggle
pomoclaw://stop                      # Stop and reset
pomoclaw://status                    # Write status to ~/.pomoclaw/status.json
pomoclaw://break?minutes=N           # Start break timer for N minutes
pomoclaw://skip                      # Skip current break
```
Confidence
60% confidence
Finding
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.

Static analysis

No suspicious patterns detected.