T09 · Insecure Skill Coding Practices
- Location
lib/automation.py:548- Finding
Macro Playback Bypasses the Central Safe-Mode Interlock
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a disclosed desktop automation skill, but its high-impact mouse, keyboard, screen, clipboard, and macro powers have safety-control gaps that warrant careful review before installing.
Install only if you are comfortable granting the skill control over your desktop session. Use it in a dedicated profile or non-sensitive environment, avoid recording while entering secrets, do not play macros from untrusted sources, keep safe mode enabled, and treat generated macro, log, screenshot, and report files as sensitive.
lib/automation.py:548Macro Playback Bypasses the Central Safe-Mode Interlock
lib/automation.py:477Conditional Screen Monitoring Executes Nested Actions Without Safety Validation
scripts/record_macro.py:219Global Macro Recorder Stores Sensitive Keystrokes and Window Titles in Plaintext
requirements.txt:1Dependency Manifest Uses Unbounded Minimum Versions and Conflicts with Declared Pins
lib/advanced_automation.py:369Protected Macro Passwords Use a Fast Unsalted Key Derivation
lib/advanced_automation.py:500Generated Macro Reports Allow Stored HTML and Script Injection
Macro: {macro_path}
Generated: {timestamp}
| # | Action | Params | Result |
|---|---|---|---|
| {i+1} | {act.get('action')} | {act.get('params')} | {act.get('result')} |
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
# Desktop Automation Skill for OpenClaw
**âš ï¸ PRIVACY WARNING**: The macro recorder captures **ALL** keyboard events (including passwords, credit card numbers, private messages) and window titles. **Never record while entering credentials.** Only use for non-sensitive workflows. Store recorded macros securely.
This script implements global keyboard and mouse capture, including all keystrokes and active window titles, then saves them to disk. Even though the UI includes a privacy warning and presents itself as a macro recorder, the functionality is effectively keylogger-like and can capture credentials, payment data, and other sensitive information from unrelated applications.
words, credit card numbers, and other sensitive data. Use with extreme caution.
Only record macros for non-sensitive workflows. Never record while entering credentials.
"""
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext, ttk
import json, os, time, threading, logging, sys
from datetime import datetime
from pynput import mouse, keyboard
from pynput.mouse import Button
from pynput.keyboard import Key
# ============ CONFIGURATION LOGGING ============
logging.basicConfig(
level=logging.INFO,
format='[%(levelname)s] %(asctime)s — %(message)s',
handlers=[logging.StreamHandler(sys.stderr)]
)
logger = logging.getLogger(__name__)
# ============ HANDLER TKINTER POUR LOGS ============
class TkinterLogHandler(logging.Handler):
"""Handler qui écrit dans un widget ScrolledText de Tkinter"""
def __init__(self, text_widget, max_lines=100):
super().__init__()
self.text_widget = text_widget
self.max_lines = max_lines
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
except Exception as e:
raise IOError(f"Dossier de sortie inaccessible ({output_dir}) : {e}")
# Reset state
self.output_path = output_path
self.recording = True
self.events = []
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
def test_dangerous_pattern_detection(self):
"""Test dangerous pattern detection."""
self.assertTrue(self.manager.contains_dangerous_pattern("rm /etc/"))
self.assertFalse(self.manager.contains_dangerous_pattern("echo hello"))
def test_check_action_safety(self):
The monitor_screen parameter example hard-codes lang: "fra", which suggests the skill expects or defaults to a specific language locale in its usage guidance. The README does not present this as user-selectable in that example or justify a region-specific constraint, so it may violate the language/locale policy requirement.
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.
}
### excel_write
Write an array of objects (or array of arrays) to an Excel file.
```javascript
The README makes a strong safety claim that risky actions are blocked by default, while elsewhere it documents direct use of typing, clicking, key presses, macro playback, and credential-entry examples without clearly showing the gating model. If the implementation does not actually enforce safe mode exactly as described, users may trust the docs and run destructive desktop automation believing safeguards are active.
The SKILL.md states categorically that 'All actions support dry_run=true', implying a universal non-executing test mode. However, the documented action tables and examples omit dry_run for several actions such as stop_macro, set_safe_mode, and get_safety_status, which contradicts the blanket claim rather than merely being incomplete.
The README example sets lang: "fra", and later the OCR action definitions repeatedly default lang="fra". This imposes a specific locale choice in the skill's natural-language interface without offering user choice or documenting a region-specific reason, which matches the locale policy violation criteria.
The core action table specifies lang="fra" as the default for several OCR-related actions. Because this is a natural-language/documentation-level locale default applied broadly, it violates the policy unless users are clearly given a language choice or the French-only behavior is justified.
The documentation explicitly provides a global mechanism to disable safe mode via an environment variable, undermining the skill's primary security control. In a desktop automation skill that can type, click, capture screenshots, read OCR text, manipulate the clipboard, and replay macros, disabling safety checks materially increases the risk of destructive actions, secret capture, or unsafe automation execution.
export AUTOMATION_LOG_DIR=~/my_logs
export AUTOMATION_SAFE_MODE=false
---
The screenshot action captures the full screen and writes it to disk without any explicit user confirmation, notice, or policy gating. In a desktop automation skill, this can expose sensitive on-screen information such as passwords, messages, tokens, or confidential documents, and the saved file creates a persistent artifact that may be accessed later.
The paste_from_clipboard action reads arbitrary clipboard contents and injects them into the currently active application without confirmation or destination validation. This can unintentionally disclose secrets copied by the user, such as passwords, API keys, or private text, into chat windows, terminals, or web forms, especially because active-window context may change unexpectedly.
These functions take screenshots of the user's screen and extract visible text, which can include sensitive or private information. While there is internal logging, there is no confirmation prompt, user-visible notice, or comment/docstring warning about the privacy impact of capturing and analyzing on-screen content.
The function signature and documentation set the OCR language default to 'fra', making French the assumed language unless the caller overrides it. This is a natural-language policy concern because it forces a locale choice by default rather than prompting for or negotiating the user's preferred language.
This monitor routine can automatically trigger actions such as click, type, scroll, drag, clipboard operations, and window activation based on screen contents. Although the behavior is central to automation, the function provides no user-facing disclosure or warning that it may take control of the UI and affect data or application state.
When evaluating text conditions, the monitor function falls back to 'fra' if no language is provided. This propagates a forced locale assumption into automated monitoring behavior without giving the user an explicit language choice.
Macro playback loads events from a file and dispatches any action present in globals() without a strict allowlist. If an attacker can supply or modify a macro file, they may trigger arbitrary exported automation functions, causing unintended keyboard/mouse control, clipboard access, window activation, or other side effects on the host.
The stop manager advertises an emergency hotkey but never sets stop_requested from keyboard events and does not actually detect the configured stop_hotkey. In an automation module that can control mouse and keyboard, a nonfunctional kill switch is a real safety issue because runaway macros may continue interacting with the system without an effective user stop path.
If safety.py is missing, the code disables safety enforcement entirely by setting get_safety and set_safe_mode to None and continues operating with only a warning. For a library that can capture screens, read OCR text, manipulate windows, control mouse/keyboard, and launch macro subprocesses, fail-open security is dangerous because all protective validation is silently bypassed.
set_safe_mode = safety.set_safe_mode
else:
get_safety = None
set_safe_mode = None
logging.warning("safety.py not available — security features disabled")
logger = logging.getLogger(__name__)
The screenshot function captures the entire screen and writes it to disk by default on the user's Desktop without any consent prompt, masking, or disclosure. In a desktop automation skill, screenshots can easily contain credentials, private messages, documents, or other sensitive material, so silent capture creates a meaningful privacy and data-exposure risk.
The function hard-codes a default OCR language of 'fra', which imposes a specific locale choice without user opt-in. This can conflict with organizational language/locale policies when the skill is used in multilingual or non-French contexts.
This OCR extraction routine processes all visible screen text, optionally from the full screen, and returns structured text plus coordinates/confidence metadata without any user-facing disclosure or minimization. In an automation-agent setting, that can expose emails, secrets, financial data, health information, or internal documents at scale, making it more dangerous than ordinary app telemetry.
The OCR extraction function forces 'fra+eng' as the recognition languages, which embeds a locale/language policy directly in the implementation. There is no indication that users can choose or opt into these language settings based on their context.
The function creates and saves an Excel workbook to the provided path, affecting user data on disk. It lacks a user-facing confirmation, visible disclosure, or warning in comments/docstrings that it will write or overwrite a file.
Detected: suspicious.dangerous_exec, suspicious.dynamic_code_execution