Back to skill

Security audit

ClawHub Download Tracker

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent ClawHub download tracker with disclosed local history, optional Feishu notifications, and optional user-configured scheduling.

Install only if you want a local ClawHub download monitor with optional Feishu notifications. Prefer real environment variables or a tightly permissioned `.env` file containing only the three Feishu keys, review the launchd plist before enabling scheduled runs, and expect the tool to run `clawhub inspect` for monitored slugs and write local history under the tracker data directory.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
clawhub_tracker.py:33
Finding

Unrestricted .env Variables Propagate to the ClawHub Subprocess

Content
View full analysis

Vulnerability Details

File Location: clawhub_tracker.py:33-43, 225-228
Vulnerability Type: Environment poisoning through unrestricted configuration loading
Risk Level: Medium

Vulnerable Code

python
_env_path = os.path.join(DATA_DIR, ".env")
if os.path.exists(_env_path):
    with open(_env_path) as _f:
        for _line in _f:
            _line = _line.strip()
            if "=" in _line and not _line.startswith("#"):
                _k, _, _v = _line.partition("=")
                os.environ.setdefault(_k.strip(), _v.strip())

APP_ID = os.environ.get("CLAWHUB_FEISHU_APP_ID", "")
APP_SECRET = os.environ.get("CLAWHUB_FEISHU_APP_SECRET", "")
USER_OPEN_ID = os.environ.get("CLAWHUB_FEISHU_USER_OPEN_ID", "")

The resulting process environment is implicitly inherited here:

python
r = subprocess.run(
    [CLAWHUB_BIN, "inspect", slug, "--json"],
    capture_output=True, text=True, timeout=15,
)

Technical Analysis

The .env parser accepts every variable name and inserts it into the global process environment, even though the application only requires three Feishu settings. No allowlist, key validation, or subprocess environment sanitization is applied.

When subprocess.run is called without an explicit env argument, the clawhub child process inherits the modified environment. Consequently, an attacker who can write the tracker’s .env file may define runtime-control or tool-specific variables rather than merely changing Feishu settings. Depending on how the installed clawhub executable is implemented, variables such as NODE_OPTIONS, PYTHONPATH, or ClawHub-specific configuration variables could modify module loading, runtime behavior, network destinations, or credential handling.

This does not independently grant write access to .env; exploitation requires an attacker or compromised process that can already modify the tracker data directory. However, it converts data-directory write access into a potential exec ...[truncated 1458 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not copy arbitrary .env entries into os.environ.
  2. Allowlist only the three supported keys:
    • CLAWHUB_FEISHU_APP_ID
    • CLAWHUB_FEISHU_APP_SECRET
    • CLAWHUB_FEISHU_USER_OPEN_ID
  3. Store parsed values in a private configuration dictionary rather than modifying the process-wide environment.
  4. Supply an explicit, sanitized environment to subprocess.run. Preserve only variables necessary to locate and operate the trusted executable.
  5. Validate .env ownership and permissions before reading it, and document mode 0600 for the file and 0700 for its directory.
  6. Resolve and validate the clawhub executable path before execution.

Example hardening approach:

python
ALLOWED_ENV_KEYS = {
    "CLAWHUB_FEISHU_APP_ID",
    "CLAWHUB_FEISHU_APP_SECRET",
    "CLAWHUB_FEISHU_USER_OPEN_ID",
}

config = {}
if os.path.exists(_env_path):
    with open(_env_path, encoding="utf-8") as env_file:
        for line in env_file:
            line = line.strip()
            if not line or line.startswith("#") or "=" not in line:
                continue
            key, value = line.split("=", 1)
            key = key.strip()
            if key in ALLOWED_ENV_KEYS:
                config[key] = value.strip()

APP_ID = os.environ.get(
    "CLAWHUB_FEISHU_APP_ID",
    config.get("CLAWHUB_FEISHU_APP_ID", ""),
)

Use a sanitized child environment:

python
child_env = {
    "PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin",
    "HOME": os.path.expanduser("~"),
}

r = subprocess.run(
    [CLAWHUB_BIN, "inspect", slug, "--json"],
    capture_output=True,
    text=True,
    timeout=15,
    env=child_env,
)

T09 · Insecure Skill Coding Practices

Note
Location
clawhub_tracker.sh:7
Finding

Predictable Shared Temporary Log Permits Symlink Attacks

Content
View full analysis

Vulnerability Details

File Location: clawhub_tracker.sh:7-10
Vulnerability Type: Unsafe predictable file in a globally writable temporary directory
Risk Level: Low

Vulnerable Code

bash
LOG="/tmp/clawhub_tracker_launchd.log"

echo "[$(date)] 开始执行" >> "$LOG"
OUTPUT=$(/usr/bin/python3 "$SCRIPT" 2>&1)
echo "$OUTPUT" >> "$LOG"

Technical Analysis

The launchd wrapper appends output to a fixed pathname in /tmp. The directory is globally writable, and the script does not securely create the file, verify its owner, reject symbolic links, or enforce restrictive permissions.

Shell redirection normally follows symbolic links. Another local user may therefore create /tmp/clawhub_tracker_launchd.log as a symlink to a file writable by the victim account. When the scheduled job runs, it opens the symlink target and appends tracker output. This is a time-of-check/time-of-use-resistant attack because the script performs no ownership or link checks at all.

The attack cannot overwrite arbitrary root-owned files because the launchd agent runs as the user, not as root, and append redirection still follows normal filesystem permissions. Nevertheless, it may corrupt user-owned configuration or data files. The log can also disclose monitored skill names, download counts, execution timing, and errors to other local users if the resulting file mode is permissive.

Attack Path

  1. A local attacker determines the victim uses the documented launchd wrapper.

  2. The attacker creates the predictable path as a symbolic link:

    bash
    ln -s /path/to/victim-writable-target /tmp/clawhub_tracker_launchd.log
    
  3. The victim’s launchd agent executes clawhub_tracker.sh.

  4. The first echo redirection follows the symbolic link and appends to the selected target.

  5. The Python tracker executes, and its combined standard output and standard error are captured.

  6. The second redirection again follows the link and appends the captured content.

...[truncated 586 chars]

Remediation
View remediation

Remediation Suggestions

  1. Store wrapper logs in the private tracker data directory rather than /tmp.
  2. Create the directory with mode 0700 and the log with mode 0600.
  3. Refuse to use a path that is a symbolic link or not owned by the current user.
  4. Prefer launchd’s StandardOutPath and StandardErrorPath, pointing to securely created user-owned files.
  5. Avoid capturing all output in a shell variable; redirect the Python process directly to the secure log.

Example:

bash
#!/bin/bash
set -eu
umask 077

export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
SCRIPT="$HOME/.openclaw/workspace/skills/clawhub-download-tracker/clawhub_tracker.py"
LOG_DIR="$HOME/.openclaw/workspace/data/clawhub-tracker"
LOG="$LOG_DIR/launchd.log"

mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"

if [ -L "$LOG" ]; then
    echo "Refusing to write through a symbolic link" >&2
    exit 1
fi

touch "$LOG"
chmod 600 "$LOG"

{
    printf '[%s] Starting tracker\n' "$(date)"
    /usr/bin/python3 "$SCRIPT"
    printf '[%s] Tracker completed\n' "$(date)"
} >>"$LOG" 2>&1

For stronger protection, securely create the log during installation, verify ownership before every use, and configure launchd to write stdout and stderr directly to that established path.

Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (38)

Tainted flow: 'req' from os.environ.get (line 112, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · clawhub_tracker.py (reported line 95)May include surrounding context.

python
data=data, headers={"Content-Type": "application/json"}, method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=10) as r:
            return json.loads(r.read().decode()).get("tenant_access_token", "")
    except Exception as e:
        log(f"token fetch failed: {e}")

Tainted flow: 'req' from os.environ.get (line 112, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · clawhub_tracker.py (reported line 122)May include surrounding context.

python
data=data, headers={"Content-Type": "application/json"}, method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=10) as r:
            return json.loads(r.read().decode()).get("tenant_access_token", "")
    except Exception as e:
        log(f"token fetch failed: {e}")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 134)May include surrounding context.

md
|----------|----------|
| Slug not found in ClawHub | Mark as fetch failed, skip |
| Invalid slug format | Reject (regex validation, prevents injection) |
| Missing .env | Skip Feishu push, continue with local files |
| Empty skills.csv | Send "no skills to monitor" notice to Feishu, exit |
| Concurrent runs | Second instance detects lock, exits gracefully |
| checklog missing (e.g. migration) | Fall back to last_state.json for delta |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 143)May include surrounding context.

md
- `test_clawhub_tracker.py` — test suite

Credential Access

High
Category
Privilege Escalation
Confidence
77% confidence
Finding

The script loads Feishu credentials from a plaintext .env file under the user's home workspace without enforcing restrictive permissions or using a dedicated secret store. If that directory is backed up, synced, shared, or readable by other local users/processes, the app secret can be disclosed and abused to send messages or impersonate this integration. In this skill context, the data is not system-critical, but it still exposes reusable API credentials.

Content

Scanner excerpt · clawhub_tracker.py (reported line 38)May include surrounding context.

python
os.makedirs(DATA_DIR, exist_ok=True)
os.makedirs(REPORT_DIR, exist_ok=True)

# 从环境变量或 .env 文件读取飞书凭证(不硬编码)
_env_path = os.path.join(DATA_DIR, ".env")
if os.path.exists(_env_path):
    with open(_env_path) as _f:

Credential Access

High
Category
Privilege Escalation
Confidence
77% confidence
Finding

Reading a local .env file for secrets is a real credential-handling weakness because it normalizes plaintext secret storage in an application data directory. An attacker with local read access, a compromised backup/sync target, or accidental inclusion of the directory in archives could recover the Feishu app secret and reuse it. The skill's notification functionality makes this more dangerous than a harmless config file because the secret grants API access.

Content

Scanner excerpt · clawhub_tracker.py (reported line 39)May include surrounding context.

python
os.makedirs(REPORT_DIR, exist_ok=True)

# 从环境变量或 .env 文件读取飞书凭证(不硬编码)
_env_path = os.path.join(DATA_DIR, ".env")
if os.path.exists(_env_path):
    with open(_env_path) as _f:
        for _line in _f:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 328)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 434)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 328)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 337)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 434)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 328)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 328)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 328)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 337)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 434)May include surrounding context.

python
t.ok("slug_valid: 合法 slug 通过")

    # 非法 slug
    for invalid in ['', ' ', '; rm -rf /', '../etc/passwd', 'foo bar', 'slug;whoami', '$(id)', 'Aaa', '-dash-start']:
        if tracker._valid_slug(invalid):
            t.fail("slug_invalid", f"非法 slug 未被拒绝: {invalid}")
            return

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 337)May include surrounding context.

python
def test_slug_injection_in_fetch(t):
    """fetch() 对非法 slug 返回 None 而非执行子进程"""
    result = tracker.fetch("; rm -rf /")
    if result is None:
        t.ok("fetch_injection: 注入 slug 返回 None")
    else:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 337)May include surrounding context.

python
def test_slug_injection_in_fetch(t):
    """fetch() 对非法 slug 返回 None 而非执行子进程"""
    result = tracker.fetch("; rm -rf /")
    if result is None:
        t.ok("fetch_injection: 注入 slug 返回 None")
    else:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 337)May include surrounding context.

python
def test_slug_injection_in_fetch(t):
    """fetch() 对非法 slug 返回 None 而非执行子进程"""
    result = tracker.fetch("; rm -rf /")
    if result is None:
        t.ok("fetch_injection: 注入 slug 返回 None")
    else:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 434)May include surrounding context.

python
if not os.path.exists(os.path.join(m.dir, "skills.csv")):
            pass
        # cmd_add 内部已校验,直接测 _valid_slug 行为
        invalid_cases = ["; rm -rf /", "../etc/passwd", "FOO", "-leading-dash", "with space"]
        for bad in invalid_cases:
            if tracker._valid_slug(bad):
                t.fail("add_invalid", f"非法 slug 通过校验: {bad}")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
100% confidence
Finding

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).

Content

Scanner excerpt · test_clawhub_tracker.py (reported line 434)May include surrounding context.

python
if not os.path.exists(os.path.join(m.dir, "skills.csv")):
            pass
        # cmd_add 内部已校验,直接测 _valid_slug 行为
        invalid_cases = ["; rm -rf /", "../etc/passwd", "FOO", "-leading-dash", "with space"]
        for bad in invalid_cases:
            if tracker._valid_slug(bad):
                t.fail("add_invalid", f"非法 slug 通过校验: {bad}")

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · README.md (reported line 33)May include surrounding context.

2. Configure Feishu (optional, only for push notifications)

Create ~/.openclaw/workspace/data/clawhub-tracker/.env:

text
CLAWHUB_FEISHU_APP_ID=cli_xxx

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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.

Content

Scanner excerpt · README.md (reported line 88)May include surrounding context.

Scheduling with launchd

A wrapper script clawhub_tracker.sh sets up PATH for the cron/launchd environment. Example plist (~/Library/LaunchAgents/com.you.clawhub-tracker.plist):

xml
<?xml version="1.0" encoding="UTF-8"?>

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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.

Content

Scanner excerpt · README.md (reported line 92)May include surrounding context.

Scheduling with launchd

A wrapper script clawhub_tracker.sh sets up PATH for the cron/launchd environment. Example plist (~/Library/LaunchAgents/com.you.clawhub-tracker.plist):

xml
<?xml version="1.0" encoding="UTF-8"?>

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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.

Content

Scanner excerpt · README.md (reported line 93)May include surrounding context.

Scheduling with launchd

A wrapper script clawhub_tracker.sh sets up PATH for the cron/launchd environment. Example plist (~/Library/LaunchAgents/com.you.clawhub-tracker.plist):

xml
<?xml version="1.0" encoding="UTF-8"?>

Static analysis

No suspicious patterns detected.