applescript

安装量: 141
排名: #6063

安装

npx skills add https://github.com/martinholovsky/claude-skills-generator --skill applescript
  1. Overview

Risk Level: HIGH - Shell command execution, application control, file system access

You are an expert in AppleScript automation with deep expertise in:

AppleScript Language: Script composition, application scripting dictionaries JavaScript for Automation (JXA): Modern alternative with JavaScript syntax osascript Execution: Command-line script execution and security Sandboxing Considerations: App sandbox restrictions and automation permissions Core Expertise Areas Script Composition: Secure AppleScript/JXA patterns Application Automation: Scriptable app interaction Security Controls: Input sanitization, command filtering Process Management: Safe execution with timeouts 2. Core Responsibilities 2.1 Core Principles

When creating or executing AppleScripts:

TDD First - Write tests before implementing AppleScript automation Performance Aware - Cache scripts, batch operations, minimize app activations Sanitize all inputs before script interpolation Block dangerous commands (rm, sudo, curl piped to sh) Validate target applications against blocklist Enforce execution timeouts Log all script executions 2.2 Security-First Approach

Every script execution MUST:

Sanitize user-provided inputs Check for dangerous patterns Validate target applications Execute with timeout limits Log execution details 2.3 Blocked Operations

Never allow scripts that:

Execute arbitrary shell commands without validation Access password managers or security tools Modify system files or preferences Download and execute code Access financial applications 3. Technical Foundation 3.1 Execution Methods

Command Line: osascript

osascript -e 'tell application "Finder" to activate' osascript script.scpt osascript -l JavaScript -e 'Application("Finder").activate()'

Python Integration: subprocess or py-applescript

import subprocess result = subprocess.run(['osascript', '-e', script], capture_output=True)

3.2 Key Security Considerations Risk Area Mitigation Priority Command injection Input sanitization CRITICAL Shell escape Use quoted form of CRITICAL Privilege escalation Block do shell script with admin HIGH Data exfiltration Block network commands HIGH 4. Implementation Patterns Pattern 1: Secure Script Execution import subprocess, re, logging

class SecureAppleScriptRunner: BLOCKED_PATTERNS = [ r'do shell script.with administrator', r'do shell script.sudo', r'do shell script.(rm -rf|rm -r)', r'do shell script.curl.|.sh', r'keystroke.*password', ] BLOCKED_APPS = ['Keychain Access', '1Password', 'Terminal', 'System Preferences']

def __init__(self, permission_tier: str = 'standard'):
    self.permission_tier = permission_tier
    self.logger = logging.getLogger('applescript.security')

def execute(self, script: str, timeout: int = 30) -> tuple[str, str]:
    self._check_blocked_patterns(script)
    self._check_blocked_apps(script)
    self.logger.info(f'applescript.execute', extra={'script': script[:100]})
    try:
        result = subprocess.run(['osascript', '-e', script],
            capture_output=True, text=True, timeout=timeout)
        return result.stdout.strip(), result.stderr.strip()
    except subprocess.TimeoutExpired:
        raise TimeoutError(f"Script timed out after {timeout}s")

def _check_blocked_patterns(self, script: str):
    for pattern in self.BLOCKED_PATTERNS:
        if re.search(pattern, script, re.IGNORECASE):
            raise SecurityError(f"Blocked pattern: {pattern}")

def _check_blocked_apps(self, script: str):
    for app in self.BLOCKED_APPS:
        if app.lower() in script.lower():
            raise SecurityError(f"Access to {app} blocked")

Pattern 2: Safe Input Interpolation class SafeScriptBuilder: """Build AppleScript with safe input interpolation."""

@staticmethod
def escape_string(value: str) -> str:
    """Escape string for AppleScript interpolation."""
    # Escape backslashes and quotes
    escaped = value.replace('\\', '\\\\').replace('"', '\\"')
    return escaped

@staticmethod
def quote_for_shell(value: str) -> str:
    """Quote value for shell command within AppleScript."""
    # Use AppleScript's quoted form of
    return f'quoted form of "{SafeScriptBuilder.escape_string(value)}"'

def build_tell_script(self, app_name: str, commands: list[str]) -> str:
    """Build safe tell application script."""
    # Validate app name
    if not re.match(r'^[a-zA-Z0-9 ]+$', app_name):
        raise ValueError("Invalid application name")

    escaped_app = self.escape_string(app_name)
    escaped_commands = [self.escape_string(cmd) for cmd in commands]

    script = f'''

tell application "{escaped_app}" {chr(10).join(escaped_commands)} end tell ''' return script.strip()

def build_safe_shell_command(self, command: str, args: list[str]) -> str:
    """Build safe do shell script command."""
    # Allowlist of safe commands
    SAFE_COMMANDS = ['ls', 'pwd', 'date', 'whoami', 'echo']

    if command not in SAFE_COMMANDS:
        raise SecurityError(f"Command {command} not in allowlist")

    # Quote all arguments
    quoted_args = ' '.join(f'"{self.escape_string(arg)}"' for arg in args)

    return f'do shell script "{command} {quoted_args}"'

Pattern 3: JXA (JavaScript for Automation) class SecureJXARunner { constructor() { this.blockedApps = ['Keychain Access', 'Terminal', 'System Preferences']; }

runApplication(appName, action) {
    if (this.blockedApps.includes(appName)) {
        throw new Error(`Access to ${appName} is blocked`);
    }
    return Application(appName)[action]();
}

safeShellScript(command) {
    const blocked = [/rm\s+-rf/, /sudo/, /curl.*\|.*sh/];
    for (const p of blocked) {
        if (p.test(command)) throw new Error('Blocked command');
    }
    const app = Application.currentApplication();
    app.includeStandardAdditions = true;
    return app.doShellScript(command);
}

}

Pattern 4: Application Dictionary Validation class AppDictionaryValidator: def get_app_dictionary(self, app_name: str) -> str: result = subprocess.run(['sdef', f'/Applications/{app_name}.app'], capture_output=True, text=True) return result.stdout

def is_scriptable(self, app_name: str) -> bool:
    try:
        return bool(self.get_app_dictionary(app_name).strip())
    except Exception:
        return False
  1. Implementation Workflow (TDD) Step 1: Write Failing Test First import pytest

class TestSecureAppleScriptRunner: def test_simple_script_execution(self): runner = SecureAppleScriptRunner() stdout, stderr = runner.execute('return "hello"') assert stdout == "hello"

def test_blocked_pattern_raises_error(self):
    runner = SecureAppleScriptRunner()
    with pytest.raises(SecurityError):
        runner.execute('do shell script "rm -rf /"')

def test_blocked_app_raises_error(self):
    runner = SecureAppleScriptRunner()
    with pytest.raises(SecurityError):
        runner.execute('tell application "Keychain Access" to activate')

def test_timeout_enforcement(self):
    runner = SecureAppleScriptRunner()
    with pytest.raises(TimeoutError):
        runner.execute('delay 10', timeout=1)

Step 2: Implement Minimum to Pass class SecureAppleScriptRunner: def execute(self, script: str, timeout: int = 30): self._check_blocked_patterns(script) self._check_blocked_apps(script) result = subprocess.run(['osascript', '-e', script], capture_output=True, text=True, timeout=timeout) return result.stdout.strip(), result.stderr.strip()

Step 3: Refactor and Verify pytest tests/test_applescript.py -v pytest tests/test_applescript.py -k "blocked or security" -v

  1. Performance Patterns Pattern 1: Script Caching

BAD: Recompile script every execution

result = subprocess.run(['osascript', '-e', script], capture_output=True)

GOOD: Cache compiled scripts

class CachedScriptRunner: cache = {} def execute_cached(self, script_id: str, script: str): if script_id not in self._cache: import tempfile , path = tempfile.mkstemp(suffix='.scpt') subprocess.run(['osacompile', '-o', path, '-e', script]) self._cache[script_id] = path return subprocess.run(['osascript', self._cache[script_id]], capture_output=True)

Pattern 2: Batch Operations

BAD: Multiple separate script calls

subprocess.run(['osascript', '-e', f'tell app "{app}" to set bounds...']) subprocess.run(['osascript', '-e', f'tell app "{app}" to activate'])

GOOD: Single batched script

script = f'''tell application "{app}" set bounds of window 1 to {{{x}, {y}, {w}, {h}}} activate end tell''' subprocess.run(['osascript', '-e', script], capture_output=True)

Pattern 3: Async Execution

BAD: Blocking execution

result = subprocess.run(['osascript', '-e', script], capture_output=True)

GOOD: Async execution

async def run_script_async(script: str, timeout: int = 30): proc = await asyncio.create_subprocess_exec('osascript', '-e', script, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout) return stdout.decode().strip(), stderr.decode().strip()

Pattern 4: Result Filtering

BAD: Return full unfiltered output

script = 'tell app "System Events" to get properties of every window of every process'

GOOD: Filter in AppleScript

script = '''tell application "System Events" set windowList to {} repeat with proc in (processes whose visible is true) set end of windowList to name of window 1 of proc end repeat return windowList end tell'''

Pattern 5: Minimal App Activation

BAD: Activate app for every operation

subprocess.run(['osascript', '-e', f'tell app "{app}" to activate'])

GOOD: Use background operations via System Events

script = f'''tell application "System Events" tell process "{app}" click button "{button}" of window 1 end tell end tell'''

  1. Security Standards 7.1 Critical Vulnerabilities
  2. Command Injection (CWE-78) Severity: CRITICAL Description: Unsanitized input in do shell script Mitigation: Always use quoted form of, validate inputs
  3. Privilege Escalation (CWE-269) Severity: CRITICAL Description: do shell script with administrator privileges Mitigation: Block admin privilege requests
  4. Script Injection (CWE-94) Severity: HIGH Description: Injected AppleScript code Mitigation: Never interpolate untrusted data into scripts
  5. Path Traversal (CWE-22) Severity: HIGH Description: File operations with unsanitized paths Mitigation: Validate and canonicalize paths
  6. Information Disclosure (CWE-200) Severity: MEDIUM Description: Scripts exposing sensitive data Mitigation: Filter sensitive output, audit logging 7.2 OWASP Mapping OWASP ID Category Risk Mitigation A05:2025 Injection CRITICAL Input sanitization, command allowlists A01:2025 Broken Access Control HIGH Application blocklists A02:2025 Security Misconfiguration MEDIUM Secure defaults
  7. Common Mistakes Never: Interpolate Untrusted Input Directly -- BAD: Direct interpolation set userInput to "test; rm -rf /" do shell script "echo " & userInput

-- GOOD: Use quoted form of set userInput to "test; rm -rf /" do shell script "echo " & quoted form of userInput

Never: Allow Administrator Privileges

BAD: Allow admin scripts

script = 'do shell script "..." with administrator privileges' runner.execute(script)

GOOD: Block admin privilege requests

if 'with administrator' in script: raise SecurityError("Administrator privileges blocked")

Never: Execute User-Provided Scripts

BAD: Execute arbitrary user script

user_script = request.body['script'] runner.execute(user_script)

GOOD: Use templates with validated parameters

template = 'tell application "Finder" to activate' runner.execute(template)

  1. Pre-Implementation Checklist Phase 1: Before Writing Code Write failing tests for security controls Write failing tests for expected functionality Review blocked patterns list for completeness Identify which applications will be scripted Plan input sanitization approach Phase 2: During Implementation Input sanitization for all user data Blocked pattern detection enabled Application blocklist configured Command allowlist for shell scripts Timeout enforcement Audit logging enabled Use quoted form of for all shell arguments Cache compiled scripts for reuse Phase 3: Before Committing All tests pass: pytest tests/test_applescript.py -v Security tests pass: pytest -k "blocked or security" Injection attack tests verified Timeout handling tests verified Permission tier tests verified No hardcoded credentials or paths Audit logging verified functional
  2. Summary

Your goal is to create AppleScript automation that is:

Secure: Input sanitization, command filtering, application blocklists Reliable: Timeout enforcement, proper error handling Auditable: Comprehensive logging of all executions

Security Reminders:

Always use quoted form of for shell arguments Never interpolate untrusted data into scripts Block administrator privilege requests Maintain strict command allowlists Log all script executions References Security Examples: See references/security-examples.md Threat Model: See references/threat-model.md Advanced Patterns: See references/advanced-patterns.md

返回排行榜