Back to skill

Security audit

Plant Tracker

Security checks for vulnerabilities and agentic risk

Overview

The plant tracker is mostly coherent, but its export command can overwrite broad areas of the user's home directory, which is more authority than a plant-data export needs.

Review the export behavior before installing. Use exports only to clearly intended Markdown files, preferably inside ~/.openclaw/workspace or a dedicated exports folder, and avoid letting the skill write to existing home-directory configuration files or application data.

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/plant_tracker.py:218
Finding
Unsafe Export Path Validation Allows Arbitrary Home-File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/plant_tracker.py:218-226, 248-277` **Vulnerability Type**: Arbitrary file overwrite through incomplete path restrictions and unsafe path-prefix validation **Risk Level**: High ### Vulnerable Code ```python # Security: Validate output path output_path = Path(output_file) if not is_safe_path(output_path): print(f"❌ Security error: Cannot write to '{output_path}'") print(" Path must be within workspace or home directory (not system paths)") return False # Ensure parent directory exists output_path.parent.mkdir(parents=True, exist_ok=True) ``` ```python output_path.write_text(md) print(f"✓ Exported {len(plants)} plants to {output_path}") return True def is_safe_path(filepath): """Check if file path is within safe directories (workspace, home, or /tmp).""" try: path = Path(filepath).expanduser().resolve() workspace = Path.home() / ".openclaw" / "workspace" home = Path.home() tmp = Path("/tmp") path_str = str(path) workspace_str = str(workspace.resolve()) home_str = str(home.resolve()) tmp_str = str(tmp.resolve()) in_workspace = path_str.startswith(workspace_str) in_home = path_str.startswith(home_str) in_tmp = path_str.startswith(tmp_str) # Block system paths system_dirs = ["/etc", "/usr", "/var", "/root", "/bin", "/sbin", "/lib", "/lib64", "/opt", "/boot", "/proc", "/sys"] blocked = any(path_str.startswith(d) for d in system_dirs) # Block sensitive dotfiles in home directory sensitive_patterns = [".ssh", ".bashrc", ".zshrc", ".profile", ".bash_profile", ".config/autostart"] for pattern in sensitive_patterns: if pattern in path_str: blocked = True break return (in_workspace or in_tmp or in_home) and not blocked except Exception: return False ``` ### Technical Analysis The ex ...[truncated 3402 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Restrict exports to a dedicated directory** Permit exports only beneath a directory such as: ```python export_root = ( Path.home() / ".openclaw" / "workspace" / "exports" ).resolve() ``` This is sufficient for the declared export functionality and avoids granting write access across the entire home directory. 2. **Use path-component-aware containment** Replace string-prefix checks with `Path.is_relative_to()`: ```python def is_safe_path(filepath): try: export_root = ( Path.home() / ".openclaw" / "workspace" / "exports" ).resolve() path = Path(filepath).expanduser().resolve(strict=False) return path.is_relative_to(export_root) except (OSError, RuntimeError, ValueError): return False ``` For Python versions without `is_relative_to()`, use `relative_to()` inside a `try` block. 3. **Do not rely on a sensitive-file blacklist** A blacklist cannot enumerate every configuration, credential, startup, or application-controlled file. Use an allowlisted export root and, if appropriate, require a safe extension such as `.md`. 4. **Prevent silent replacement of existing files** Refuse to overwrite existing files unless the caller explicitly requests it. For example, use exclusive creation: ```python with output_path.open("x", encoding="utf-8") as output: output.write(md) ``` If overwrite support is required, expose an explicit `--overwrite` option and clearly warn the user. 5. **Harden against symlink and race-condition attacks** Where supported, create files using no-follow and exclusive flags, verify the resolved parent directory immediately before opening the file, and avoid separate validation and write operations that can be raced. 6. **Apply secure permissions** Create export directories and files with permissions that do not expose potentially private plant note ...[truncated 222 chars]
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

Static analysis

No suspicious patterns detected.