Back to skill

Security audit

ClawTime Setup

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated ClawTime setup purpose, but its installer can run mutable remote code and writes startup scripts unsafely.

Review the installer before running it, only use configuration values you control, and prefer a pinned reviewed ClawTime commit with audited npm dependencies. Treat token display, passkey resets, device-key deletion, launchd persistence, and generated startup scripts as sensitive operations.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/install.sh:199
Finding
Command Injection Through Generated Startup Scripts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:52-55`, `scripts/install.sh:141-145`, `scripts/install.sh:199-205`, and `scripts/install.sh:231-237` **Vulnerability Type**: Shell command injection through unsafe code generation **Risk Level**: High ### Vulnerable Code User-controlled configuration is collected without restrictive validation: ```bash read -r -p " Your public URL (e.g. https://portal.yourdomain.com): " PUBLIC_URL if [ -z "$PUBLIC_URL" ]; then echo "✗ PUBLIC_URL is required." exit 1 fi ``` ```bash read -r -p "→ Bot name (press Enter for 'Beware'): " BOT_NAME BOT_NAME="${BOT_NAME:-Beware}" read -r -p "→ Bot emoji (press Enter for '🌀'): " BOT_EMOJI BOT_EMOJI="${BOT_EMOJI:-🌀}" ``` These values are then inserted directly into generated shell scripts: ```bash cat >> "$START_SERVER" <<STARTSCRIPT PUBLIC_URL=$PUBLIC_URL \\ GATEWAY_TOKEN="\$GATEWAY_TOKEN" \\ SETUP_TOKEN="\$SETUP_TOKEN" \\ BOT_NAME="$BOT_NAME" \\ BOT_EMOJI="$BOT_EMOJI" \\ ${TTS_LINE} node server.js STARTSCRIPT ``` The same unsafe interpolation occurs in `start.sh`: ```bash cat >> "$START_ALL" <<ALLSCRIPT_BODY PUBLIC_URL=$PUBLIC_URL \\ GATEWAY_TOKEN="\$GATEWAY_TOKEN" \\ SETUP_TOKEN="\$SETUP_TOKEN" \\ BOT_NAME="$BOT_NAME" \\ BOT_EMOJI="$BOT_EMOJI" \\ ${TTS_LINE} node "$INSTALL_DIR/server.js" &>/tmp/clawtime.log & ``` ### Technical Analysis The installer constructs executable shell source using values supplied interactively by the user. `PUBLIC_URL` is emitted without quoting, while `BOT_NAME` and `BOT_EMOJI` are placed inside double quotes without escaping embedded quotation marks, command substitutions, backticks, line breaks, or shell control operators. Here-document expansion occurs while the installer generates each file, and the resulting file is later parsed again as shell syntax. Consequently, input that changes the syntactic structure of an assignment can add arbitrary commands to `start-server.sh` or `start.sh`. This is a code-generation ...[truncated 2095 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not generate executable shell source by directly interpolating user input. 2. Store non-secret configuration in a structured format such as JSON and have the application parse it without `eval` or shell sourcing. 3. If shell-script generation is unavoidable, serialize every value using a shell-aware escaping mechanism such as: ```bash printf 'PUBLIC_URL=%q\n' "$PUBLIC_URL" >> "$START_SERVER" printf 'BOT_NAME=%q\n' "$BOT_NAME" >> "$START_SERVER" printf 'BOT_EMOJI=%q\n' "$BOT_EMOJI" >> "$START_SERVER" ``` 4. Validate `PUBLIC_URL` using a URL parser and require: - The `https` scheme. - A valid hostname. - No credentials, control characters, whitespace, shell syntax, or unexpected path/query components. 5. Apply explicit length and character restrictions to `BOT_NAME` and `BOT_EMOJI`. 6. Prefer passing configuration as fixed argument-array elements or through a securely generated environment file parsed without shell evaluation. 7. Add automated tests using quotation marks, command substitutions, backticks, newlines, semicolons, pipes, and redirection characters to verify that generated configuration cannot change shell syntax. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
scripts/install.sh:95
Finding
Unpinned Remote Repository Retrieval and Dependency Execution<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:95-107` **Vulnerability Type**: Mutable remote payload and supply-chain execution **Risk Level**: Medium ### Vulnerable Code ```bash if [ -d "$INSTALL_DIR/.git" ]; then echo "→ Repo found at $INSTALL_DIR — pulling latest..." cd "$INSTALL_DIR" git pull --ff-only 2>/dev/null || echo " (up to date or local changes present)" else echo "→ Cloning ClawTime to $INSTALL_DIR..." mkdir -p "$HOME/Projects" git clone "$REPO_URL" "$INSTALL_DIR" fi # ── 4. Install npm dependencies ─────────────────────────────────────────────── echo "→ Installing npm dependencies..." cd "$INSTALL_DIR" npm install --legacy-peer-deps --silent ``` The remote source is configured as: ```bash REPO_URL="https://github.com/youngkent/clawtime.git" ``` The same unsafe installation pattern is also recommended in `SKILL.md:63-67`: ```bash cd ~/Projects git clone https://github.com/youngkent/clawtime.git cd clawtime npm install --legacy-peer-deps ``` ### Technical Analysis The installer clones the current state of a remote repository or performs `git pull --ff-only` against its configured branch without pinning a reviewed commit, verifying a signed release, or checking an expected digest. It then immediately runs `npm install`. This means the effective code executed by the Skill can change after the audited package has been reviewed. The audited artifact does not contain the remotely retrieved `server.js`, `package.json`, package lockfile, or dependency code, so their security properties cannot be established from this package. `npm install` may execute lifecycle scripts from the cloned project and its dependencies, including `preinstall`, `install`, `postinstall`, and `prepare`. The use of `--legacy-peer-deps` also relaxes dependency resolution and can produce dependency trees that differ across installation times or registry state. ### Attack Path 1. An attacker compromises the upstream GitHub repository ...[truncated 1527 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the upstream source to a specific reviewed commit hash or immutable signed release tag. 2. After cloning, explicitly check out the expected commit and verify it: ```bash EXPECTED_COMMIT="reviewed-commit-hash" git checkout --detach "$EXPECTED_COMMIT" test "$(git rev-parse HEAD)" = "$EXPECTED_COMMIT" || exit 1 ``` 3. Verify signed Git tags or release artifacts against a documented trusted maintainer key. 4. Publish and verify cryptographic checksums for release archives. 5. Commit a reviewed lockfile and use: ```bash npm ci ``` instead of dynamically resolving dependencies with `npm install --legacy-peer-deps`. 6. Avoid suppressing installation output with `--silent`, particularly for security-sensitive installation failures and lifecycle-script activity. 7. Audit dependency lifecycle scripts and consider installation with scripts disabled where compatible: ```bash npm ci --ignore-scripts ``` 8. Do not automatically pull and execute the newest upstream branch. Require an explicit update operation that displays the old and new revisions and obtains user confirmation. 9. Ensure the remotely retrieved ClawTime repository and its complete dependency tree undergo a separate security review before deployment. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (64)

Credential Access

High
Category
Privilege Escalation
Content
## Getting the Gateway Token

```bash
# From macOS Keychain
security find-generic-password -s "openclaw-gateway-token" -a "$(whoami)" -w

# From config file
Confidence
74% confidence
Finding
The skill includes direct commands to retrieve the gateway token from Keychain or config and print it to stdout. While useful for administration, exposing secrets in terminal output increases the chance of leakage through shell history capture, shoulder-surfing, logs, recordings, or accidental copy/paste, especially in an agent-assisted workflow.

Credential Access

High
Category
Privilege Escalation
Content
```bash
# Reset passkeys (re-register from scratch)
echo '[]' > ~/.clawtime/credentials.json
# Restart server, then visit /?setup=<token>

# Reset device key (new keypair on next restart)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
# Restart server, then visit /?setup=<token>

# Reset device key (new keypair on next restart)
rm ~/.clawtime/device-key.json
```

---
Confidence
85% 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).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### Nuclear reset
```bash
rm ~/.clawtime/device-key.json
pkill -f "node server.js"; sleep 2
# Restart — fresh keypair generated
```
Confidence
96% confidence
Finding
The documented command `rm ~/.clawtime/device-key.json` is a destructive action that removes the device authentication key material, and in context it is paired with `pkill -f "node server.js"`, which can terminate processes based on a loose pattern. In an agent skill intended for setup and troubleshooting, this is especially dangerous because users or downstream automation may execute it verbatim, leading to account/device lockout, service disruption, and accidental impact on unrelated processes.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Important: Token Security

**Do NOT put tokens directly in plist files** — plists are plaintext XML on disk.
Instead, store tokens in macOS Keychain and use a wrapper script to load them at launch.

### Store tokens in Keychain (one-time setup)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
```bash
#!/usr/bin/env bash
# Wrapper script for launchd — loads tokens from Keychain securely
export GATEWAY_TOKEN=$(security find-generic-password -s "clawtime-gateway-token" -a "$(whoami)" -w)
export SETUP_TOKEN=$(security find-generic-password -s "clawtime-setup-token" -a "$(whoami)" -w)
Confidence
79% confidence
Finding
The wrapper script retrieves secrets from Keychain and exports them as environment variables before launching Node. Environment variables can be inherited by child processes and may be exposed to local inspection, crash reports, diagnostics, or accidental logging by the application, so this weakens secret isolation even though the source is Keychain.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### "device signature invalid"
Signature payload format mismatch. Delete the keypair and restart (new one auto-generates):
```bash
rm ~/.clawtime/device-key.json
pkill -f "node server.js"; sleep 2
# Restart with start command
```
Confidence
96% confidence
Finding
rm ~/.clawtime/device-key.json is a destructive command against security-relevant key material. In a skill that users may follow verbatim, this can be abused or accidentally triggered to rotate identity, break trust relationships, and disrupt access, especially without a warning about operational consequences.

Credential Access

High
Category
Privilege Escalation
Content
### Reset all passkeys (start fresh)
```bash
echo '[]' > ~/.clawtime/credentials.json
pkill -f "node server.js"; sleep 2
# Restart, then re-register
```
Confidence
97% confidence
Finding
Directly overwriting the credentials store destroys stored authentication material and can immediately revoke the user's ability to authenticate until passkeys are re-registered. Because this file contains credential state, a destructive write is security-sensitive and should not be offered casually in an agent troubleshooting flow.

Credential Access

High
Category
Privilege Escalation
Content
GATEWAY_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('gateway',{}).get('token',''))" 2>/dev/null)

if [ -z "$GATEWAY_TOKEN" ]; then
  # Try keychain
  GATEWAY_TOKEN=$(security find-generic-password -s "openclaw-gateway-token" -a "$(whoami)" -w 2>/dev/null || true)
fi
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
echo "→ Storing tokens securely in macOS Keychain..."
security add-generic-password -U -s "clawtime-gateway-token" -a "$(whoami)" -w "$GATEWAY_TOKEN" 2>/dev/null && \
  echo "  ✓ Gateway token stored in Keychain" || \
  echo "  ⚠️  Could not store gateway token in Keychain"
security add-generic-password -U -s "clawtime-setup-token" -a "$(whoami)" -w "$SETUP_TOKEN" 2>/dev/null && \
  echo "  ✓ Setup token stored in Keychain" || \
  echo "  ⚠️  Could not store setup token in Keychain"
Confidence
80% confidence
Finding
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
echo "→ Storing tokens securely in macOS Keychain..."
security add-generic-password -U -s "clawtime-gateway-token" -a "$(whoami)" -w "$GATEWAY_TOKEN" 2>/dev/null && \
  echo "  ✓ Gateway token stored in Keychain" || \
  echo "  ⚠️  Could not store gateway token in Keychain"
security add-generic-password -U -s "clawtime-setup-token" -a "$(whoami)" -w "$SETUP_TOKEN" 2>/dev/null && \
  echo "  ✓ Setup token stored in Keychain" || \
  echo "  ⚠️  Could not store setup token in Keychain"
Confidence
80% confidence
Finding
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Credential Access

High
Category
Privilege Escalation
Content
cat > "$START_SERVER" <<'STARTSCRIPT'
#!/usr/bin/env bash
# ClawTime server start script — tokens loaded from Keychain
cd "$(dirname "$0")"
GATEWAY_TOKEN=$(security find-generic-password -s "clawtime-gateway-token" -a "$(whoami)" -w 2>/dev/null)
SETUP_TOKEN=$(security find-generic-password -s "clawtime-setup-token" -a "$(whoami)" -w 2>/dev/null)
Confidence
75% confidence
Finding
The generated startup script retrieves secrets from Keychain and then passes them to `node server.js` as environment variables. While common, this increases exposure because same-user processes, crash reports, child processes, or debugging tools may read process environment data, and the script normalizes repeated secret access into an easily callable wrapper.

Static analysis

No suspicious patterns detected.