Back to skill

Security audit

Teleport Machine ID tbot Bootstrap (MacOS LaunchAgent)

Security checks for vulnerabilities and agentic risk

Overview

The skill's goal is legitimate and disclosed, but it installs a persistent credential-refreshing Teleport bot with insecure secret and LaunchAgent handling that deserves review before use.

Review before installing. Use only on a trusted macOS account, prefer secure secret delivery instead of command-line tokens, verify the resolved tbot binary and generated plist before loading it, reduce the recovery limit and Teleport role scope, and unload/remove the LaunchAgent and bot state when no longer needed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (5)

T06 · System Persistence

Error
Location
scripts/bootstrap_tbot_launchagent.sh:78
Finding

Persistent macOS LaunchAgent Installed and Automatically Restarted

Content
View full analysis
RunAtLoad KeepAlive StandardOutPath${OUT_DIR}/tbot.stdout.log StandardErrorPath${OUT_DIR}/tbot.stderr.log WorkingDirectory${OUT_DIR} PLIST launchctl bootout "gui/$(id -u)/${LABEL}" >/dev/null 2>&1 || true launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH" launchctl kickstart -k "gui/$(id -u)/${LABEL}" ``` ### Technical Analysis The bootstrap script creates and activates a macOS LaunchAgent configured with both `RunAtLoad` and `KeepAlive`. The agent therefore starts when the user logs in and is automatically restarted when it exits. This persistence is explicitly documented and is directly related to maintaining a Teleport Machine ID. Nevertheless, it creates a cross-session execution mechanism. The script also replaces any existing LaunchAgent using the fixed `com.openclaw.tbot` label without first confirming that the existing service belongs to this project. The persisted command uses the path returned by `command -v tbot` at installation time. If an attacker can influence the invoking environment or place a malicious `tbot` earlier in `PATH`, that executable path can be stored in the LaunchAgent. ### Attack Path 1. An attacker influences the user's `PATH` or places a malicious executable named `tbot` in a higher-priority writable directory. 2. The user runs the bootstrap script. 3. `command -v tbot` resolves the attacker-controlled executable. 4. The resulting path is written into `~/Library/LaunchAgents/com.openclaw.tbot.plist`. 5. The script immediately loads and starts the LaunchAgent. 6. The malicious executable subsequently runs at login and is restarted through `KeepAlive`. ### Impact Assessment Th ...[truncated 445 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/bootstrap_tbot_launchagent.sh:73
Finding

Unescaped User-Controlled Paths Injected into LaunchAgent XML

Content
View full analysis
"$PLIST_PATH" < Label${LABEL} ProgramArguments $(command -v tbot) start -c ${CONF_PATH} RunAtLoad KeepAlive StandardOutPath${OUT_DIR}/tbot.stdout.log StandardErrorPath${OUT_DIR}/tbot.stderr.log WorkingDirectory${OUT_DIR} PLIST ``` The path is populated from a command-line argument without XML validation: ```bash --out-dir) OUT_DIR="$2"; shift 2;; ``` ### Technical Analysis `OUT_DIR` is controlled through `--out-dir` and is used to derive `CONF_PATH`. Both values are inserted directly into an XML property list. XML metacharacters such as `&`, `<`, and `>` are not escaped. Shell quoting protects these values when used as ordinary shell arguments, but it does not protect the structure of the generated XML. A crafted directory value can make the plist invalid or inject additional XML elements into the persistent LaunchAgent configuration. Whether a particular injected structure is accepted depends on macOS plist parsing and the final document structure, but denial of service through malformed XML is directly achievable. Structurally valid injection may also alter persistent LaunchAgent properties. ### Attack Path 1. An attacker persuades a user or automation system to invoke the script with a crafted `--out-dir` containing XML markup. 2. The script creates directories using the supplied val ...[truncated 866 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/bootstrap_tbot_launchagent.sh:15
Finding

Teleport Onboarding Secrets Exposed Through Command-Line Arguments

Content
View full analysis
` or `--registration-secret `. 2. The user's shell may store the complete command in history. 3. The script stores the secret in a shell variable and appends it to the `CFG` argument array. 4. The secret appears in the argument vector of the invoked `tbot configure identity` process. 5. A local observer, monitoring product, process collector, or log pipeline records the argument. 6. The attacker uses the recovered onboarding credential to attempt unauthorized enrollment while that credential remains valid. ### Impact Assessment A stolen onboarding token or regis ...[truncated 520 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bootstrap_tbot_launchagent.sh:102
Finding

Predictable Shared Temporary Files Permit Symlink Clobbering and Information Disclosure

Content
View full analysis
/tmp/tbot-smoke.out 2>/tmp/tbot-smoke.err RC=$? set -e echo "Configured: $CONF_PATH" echo "LaunchAgent: $PLIST_PATH" echo "Identity: $IDENTITY_PATH" echo "Smoke test exit: $RC" if [[ $RC -ne 0 ]]; then echo "Smoke stderr:" sed -n '1,60p' /tmp/tbot-smoke.err fi ``` ### Technical Analysis The smoke test writes to fixed names in the globally shared `/tmp` directory. The shell opens these paths with redirection before starting `tsh`. It does not verify that the paths are regular files, does not use exclusive creation, and does not clean them up afterward. An attacker who can create files in `/tmp` can pre-create either path as a symbolic link to another file writable by the victim. When the victim runs the script, shell redirection follows the symlink and truncates the target. The diagnostic files may also contain Teleport proxy names, role or access errors, usernames, node metadata, or other operational details. Their final permissions depend on the user's `umask`, and they remain after the script exits. ### Attack Path 1. A local attacker predicts the fixed paths `/tmp/tbot-smoke.out` and `/tmp/tbot-smoke.err`. 2. The attacker creates one of those paths as a symbolic link to a file writable by the victim. 3. The victim executes the bootstrap script. 4. Shell redirection follows the symbolic link and truncates or overwrites the linked file with `tsh` output. 5. Alternatively, the attacker reads the residual smoke-test files if their permissions allow access. 6. The files remain available for subsequent collision or disclosure because no cleanup trap removes them. ### Impact Assessment The clobbering impact is limited t ...[truncated 407 chars]
Remediation
View remediation
"$TMP_DIR/stdout" 2>"$TMP_DIR/stderr" ``` ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
references/teleport-prereq-examples.yaml:29
Finding

Example Configuration Uses an Excessive Bound-Keypair Recovery Limit

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (21)

Tool Parameter Abuse

High
Category
Tool Misuse
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).

Content

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

md
## Uninstall / cleanup

- `launchctl bootout gui/$(id -u)/com.openclaw.tbot`
- `rm -f ~/Library/LaunchAgents/com.openclaw.tbot.plist`
- Remove bot files if desired: `rm -rf ~/.openclaw/workspace/tbot`

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · SKILL.md (reported line 111)May include surrounding context.

md
- `launchctl bootout gui/$(id -u)/com.openclaw.tbot`
- `rm -f ~/Library/LaunchAgents/com.openclaw.tbot.plist`
- Remove bot files if desired: `rm -rf ~/.openclaw/workspace/tbot`

Tool Parameter Abuse

High
Category
Tool Misuse
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).

Content

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

md
- `launchctl bootout gui/$(id -u)/com.openclaw.tbot`
- `rm -f ~/Library/LaunchAgents/com.openclaw.tbot.plist`
- Remove bot files if desired: `rm -rf ~/.openclaw/workspace/tbot`

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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 · SKILL.md (reported line 111)May include surrounding context.

md
- `launchctl bootout gui/$(id -u)/com.openclaw.tbot`
- `rm -f ~/Library/LaunchAgents/com.openclaw.tbot.plist`
- Remove bot files if desired: `rm -rf ~/.openclaw/workspace/tbot`

Session Persistence

Medium
Category
Rogue Agent
Confidence
92% confidence
Finding

The skill explicitly instructs creation of persistent local storage for Teleport bot state and identity material. In context this is intentional functionality, but it does establish durable credentials on disk that can survive session boundaries and be abused by other local processes or attackers if file permissions, storage location, or host trust are weak.

Content

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

md
## Workflow

1. Ensure prerequisites: `tbot`, `tsh`, writable output dir.
2. Create output + state dirs (default `~/.openclaw/workspace/tbot` and `~/.openclaw/workspace/tbot/state`).
3. Generate config via `tbot configure identity` (do not hand-write config):
   - destination should point to output dir (`file://.../tbot`)
   - storage should point to state dir (`file://.../tbot/state`)

Session Persistence

Medium
Category
Rogue Agent
Confidence
97% confidence
Finding

The LaunchAgent plist with RunAtLoad and KeepAlive creates automatic re-execution of tbot at login and after termination, providing persistence. For a tool that continuously refreshes machine identity credentials, this meaningfully increases security exposure because compromise of the user account or bot config yields a long-lived foothold and recurring credential refresh.

Content

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

md
- storage should point to state dir (`file://.../tbot/state`)
   - set proxy and join method (`bound_keypair` preferred)
   - write config file to `~/.openclaw/workspace/tbot/tbot.yaml`
4. Create LaunchAgent plist to run `tbot start -c <config>` with `RunAtLoad` + `KeepAlive`.
5. Load/start LaunchAgent.
6. Verify identity output exists and is fresh (`.../tbot/identity`).
7. Verify access path with `tsh -i <identity> --proxy=<proxy> ls`.

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

The command to bootstrap the LaunchAgent directly activates persistent background execution in the user's GUI session. While this is expected for the skill's purpose, it still constitutes a persistence mechanism that could be misused or left installed unintentionally, especially because it maintains renewable Teleport credentials.

Content

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

md
- Start once (foreground test):
  - `tbot start -c ~/.openclaw/workspace/tbot/tbot.yaml`
- LaunchAgent load:
  - `launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.tbot.plist`
- LaunchAgent restart:
  - `launchctl kickstart -k gui/$(id -u)/com.openclaw.tbot`

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 · SKILL.md (reported line 110)May include surrounding context.

bash
# Load/start
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.tbot.plist

# Restart
launchctl kickstart -k gui/$(id -u)/com.openclaw.tbot

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 · references/launchagent-notes.md (reported line 13)May include surrounding context.

bash
# Load/start
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.tbot.plist

# Restart
launchctl kickstart -k gui/$(id -u)/com.openclaw.tbot

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 · scripts/bootstrap_tbot_launchagent.sh (reported line 68)May include surrounding context.

sh
```bash
# Load/start
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.tbot.plist

# Restart
launchctl kickstart -k gui/$(id -u)/com.openclaw.tbot

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 · scripts/bootstrap_tbot_launchagent.sh (reported line 69)May include surrounding context.

sh
```bash
# Load/start
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.tbot.plist

# Restart
launchctl kickstart -k gui/$(id -u)/com.openclaw.tbot

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 · scripts/bootstrap_tbot_launchagent.sh (reported line 85)May include surrounding context.

sh
```bash
# Load/start
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.tbot.plist

# Restart
launchctl kickstart -k gui/$(id -u)/com.openclaw.tbot

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script accepts sensitive bootstrap credentials via command-line flags (--token and --registration-secret) without warning the user that these secrets may be exposed through shell history, process listings, or automation logs. In the context of a Teleport bot bootstrapper, these values can authorize identity enrollment, so inadvertent disclosure could let an attacker register or impersonate the bot.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

Defining a LaunchAgent plist path under ~/Library/LaunchAgents is part of setting up user-level persistence. In this skill's context, persistence is expected for a long-running Teleport bot, but it is still a security-relevant action because it causes ongoing background execution and automatic credential refresh.

Content

Scanner excerpt · scripts/bootstrap_tbot_launchagent.sh (reported line 43)May include surrounding context.

sh
STATE_DIR="${OUT_DIR}/state"
CONF_PATH="${OUT_DIR}/tbot.yaml"
IDENTITY_PATH="${OUT_DIR}/identity"
PLIST_PATH="${HOME}/Library/LaunchAgents/com.openclaw.tbot.plist"
LABEL="com.openclaw.tbot"

mkdir -p "$OUT_DIR" "$STATE_DIR" "${HOME}/Library/LaunchAgents"

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

Defining a LaunchAgent plist path under ~/Library/LaunchAgents is part of setting up user-level persistence. In this skill's context, persistence is expected for a long-running Teleport bot, but it is still a security-relevant action because it causes ongoing background execution and automatic credential refresh.

Content

Scanner excerpt · scripts/bootstrap_tbot_launchagent.sh (reported line 43)May include surrounding context.

sh
STATE_DIR="${OUT_DIR}/state"
CONF_PATH="${OUT_DIR}/tbot.yaml"
IDENTITY_PATH="${OUT_DIR}/identity"
PLIST_PATH="${HOME}/Library/LaunchAgents/com.openclaw.tbot.plist"
LABEL="com.openclaw.tbot"

mkdir -p "$OUT_DIR" "$STATE_DIR" "${HOME}/Library/LaunchAgents"

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

Writing a LaunchAgent plist is a concrete persistence action that causes tbot to start automatically and remain alive. While this is aligned with the skill's intended function, background persistence that maintains machine identity can be abused if the configuration, identity material, or host account is compromised.

Content

Scanner excerpt · scripts/bootstrap_tbot_launchagent.sh (reported line 66)May include surrounding context.

sh
"${CFG[@]}"

cat > "$PLIST_PATH" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script installs a persistent LaunchAgent and writes configuration/state files without an explicit confirmation or warning to the user. Persistence mechanisms are security-sensitive because they survive shell exit and can continue refreshing credentials in the background, which increases the blast radius if the host or bot configuration is compromised.

Content

No source excerpt is available for this finding.

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 · scripts/bootstrap_tbot_launchagent.sh (reported line 68)May include surrounding context.

sh
cat > "$PLIST_PATH" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>${LABEL}</string>

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 · scripts/bootstrap_tbot_launchagent.sh (reported line 106)May include surrounding context.

sh
cat > "$PLIST_PATH" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>${LABEL}</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

The launchctl bootstrap call actively registers the LaunchAgent, enabling automatic execution at login and persistence across sessions. In a credential-refreshing bot setup, this increases risk by ensuring continued background access and log generation even after the initial bootstrap, especially if users are not clearly informed.

Content

Scanner excerpt · scripts/bootstrap_tbot_launchagent.sh (reported line 86)May include surrounding context.

sh
<key>WorkingDirectory</key><string>${OUT_DIR}</string>
</dict>
</plist>
PLIST

launchctl bootout "gui/$(id -u)/${LABEL}" >/dev/null 2>&1 || true
launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH"

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The launchctl kickstart -k invocation immediately starts the persistent agent, transitioning from installation to active background execution. Combined with automatic identity refresh, this can maintain privileged access material on disk and in memory without further user interaction.

Content

Scanner excerpt · scripts/bootstrap_tbot_launchagent.sh (reported line 89)May include surrounding context.

sh
PLIST

launchctl bootout "gui/$(id -u)/${LABEL}" >/dev/null 2>&1 || true
launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH"
launchctl kickstart -k "gui/$(id -u)/${LABEL}"

sleep 2

Static analysis

Detected: suspicious.destructive_delete_command

Documentation contains a destructive delete command without an explicit confirmation gate.

Warn
Code
suspicious.destructive_delete_command
Location
SKILL.md:111