Back to skill

Security audit

Homebrew Bridge

Security checks for vulnerabilities and agentic risk

Overview

The skill has a clear purpose, but its installer creates persistent SSH wrappers with unsafe host handling and file-writing behavior that users should review before installing.

Install only if you trust the OpenClaw config, the same-LAN Mac, and the target directory. Prefer an explicit normal user@host value, keep the wrapper target directory private and owned by the installing user, and avoid running the installer as root or against shared writable directories until host validation and symlink-safe file creation are added.

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

Error
Location
scripts/install-wrapper.sh:19
Finding
SSH option injection through an unvalidated remote host<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install-wrapper.sh:19,69,85-89`; host values also originate from `scripts/install-homebrew-pack.sh:67-93,150-170` **Vulnerability Type**: SSH option injection leading to local command execution **Risk Level**: High ### Vulnerable Code ```bash # scripts/install-wrapper.sh --host) HOST="${2:-}"; shift 2 ;; ``` ```bash # scripts/install-wrapper.sh HOST=$(printf '%q' "$HOST") REMOTE_BIN=$(printf '%q' "$REMOTE_BIN") SSH_OPTS=( ``` ```bash # scripts/install-wrapper.sh run_remote() { local remote_cmd remote_cmd=$(printf '%q ' "$REMOTE_BIN" "$@") ssh "${SSH_OPTS[@]}" -T "$HOST" "bash -lc $(printf %q "$remote_cmd")" } ``` The host can also be obtained automatically from configuration without validation: ```bash # scripts/install-homebrew-pack.sh if [[ -n "$OPENCLAW_CONFIG" && -f "$OPENCLAW_CONFIG" ]] && command -v python3 >/dev/null 2>&1; then local discovered discovered="$(python3 - "$OPENCLAW_CONFIG" <<'PY' import json import sys from pathlib import Path config_path = Path(sys.argv[1]) cfg = json.loads(config_path.read_text()) channels = cfg.get("channels") or {} hosts = [] for channel in channels.values(): if not isinstance(channel, dict): continue remote_host = channel.get("remoteHost") if isinstance(remote_host, str) and remote_host.strip(): host = remote_host.strip() if host not in hosts: hosts.append(host) if len(hosts) == 1: print(hosts[0]) PY )" ``` ```bash # scripts/install-homebrew-pack.sh default_host="$(discover_default_host || true)" for tool in "${REQUESTED_TOOLS[@]}"; do host="${TOOL_HOSTS[$tool]:-$default_host}" [[ -n "$host" ]] || { echo "missing host for tool: $tool" >&2 echo "Provide --map $tool=user@host or --default-host user@host." >&2 exit 1 } remote_bin="/opt/homebrew/bin/$tool" cmd=( "$INSTALL_WRAPPER" --name "$tool" --host "$host" --remote-bin "$remote_bin" --target-di ...[truncated 2399 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject host values that begin with `-`, contain control characters, contain whitespace, or do not match an explicitly supported SSH destination format. 2. Parse and validate the username and hostname separately. Permit only expected username characters and valid DNS names, IPv4 addresses, or carefully handled IPv6 addresses. 3. Apply the same validation to explicit `--host` values, `--map` values, `--default-host`, and auto-discovered `remoteHost` values. 4. Do not rely on shell quoting as protection against option injection into downstream command-line tools. 5. Where supported by the SSH invocation design, use an option terminator before the destination. Validation is still required because SSH option-termination behavior and destination syntax should be tested against all supported client versions. 6. Consider invoking SSH with a fixed configuration and prohibiting caller-controlled SSH options. 7. Add negative tests covering values such as leading-hyphen destinations, embedded whitespace, control characters, malformed usernames, and injected `ProxyCommand` options. A defensive validation pattern should reject rather than normalize malformed input: ```bash validate_ssh_destination() { local destination="$1" [[ "$destination" != -* ]] || { echo "SSH destination must not begin with '-'" >&2 return 1 } [[ "$destination" =~ ^[A-Za-z0-9._-]+@[A-Za-z0-9.-]+$ ]] || { echo "Invalid SSH destination; expected user@host" >&2 return 1 } } validate_ssh_destination "$HOST" ``` The exact expression should be expanded deliberately if IPv6 or other SSH destination forms must be supported. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/install-wrapper.sh:45
Finding
Predictable wrapper installation follows existing symbolic links<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install-wrapper.sh:45-59,65-75,77-84,141-144` **Vulnerability Type**: Symlink-following arbitrary file overwrite and unsafe predictable file creation **Risk Level**: Medium ### Vulnerable Code ```bash safe_name="$(printf '%s' "$NAME" | tr -cd 'a-zA-Z0-9._-')" [[ -n "$safe_name" ]] || { echo "invalid wrapper name" >&2; exit 1; } [[ "$REMOTE_BIN" = /* ]] || { echo "remote-bin must be absolute" >&2; exit 1; } ``` ```bash mkdir -p "$TARGET_DIR" wrapper="$TARGET_DIR/$safe_name" ``` ```bash { cat <<EOF #!/usr/bin/env bash set -euo pipefail HOST=$(printf '%q' "$HOST") REMOTE_BIN=$(printf '%q' "$REMOTE_BIN") SSH_OPTS=( EOF for opt in "${ssh_opts[@]-}"; do [[ -n "$opt" ]] || continue printf ' %q\n' "$opt" done cat <<EOF ) WAKE_MAC=$(printf '%q' "$WAKE_MAC") WAKE_BROADCAST=$(printf '%q' "$WAKE_BROADCAST") WAKE_PORT=$(printf '%q' "$WAKE_PORT") WAKE_WAIT=$(printf '%q' "$WAKE_WAIT") WAKE_RETRIES=$(printf '%q' "$WAKE_RETRIES") ``` ```bash EOF } > "$wrapper" chmod 755 "$wrapper" echo "Installed wrapper: $wrapper" ``` ### Technical Analysis The installer creates a predictable destination path and writes to it using ordinary shell redirection: ```bash } > "$wrapper" ``` It does not inspect the destination with `lstat`, reject an existing symbolic link, use exclusive creation, or create and atomically rename a secure temporary file. Shell redirection follows an existing symlink, so the generated wrapper content is written to the symlink target. The subsequent `chmod 755` can also affect the referenced target. This becomes a privilege-boundary vulnerability when an attacker can create entries in `TARGET_DIR` and a more privileged user later runs the installer. The attacker can place a symlink at the expected wrapper path and redirect the privileged write to another file that the installer account can modify. The wrapper-name handling introduces an additional collision concern. Invalid characters are si ...[truncated 1867 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require the wrapper name to already be valid instead of silently deleting characters: ```bash [[ "$NAME" =~ ^[A-Za-z0-9._-]+$ ]] || { echo "Invalid wrapper name" >&2 exit 1 } safe_name="$NAME" ``` 2. Verify that the target directory is owned by the expected account and is not writable by less-privileged users. 3. Reject an existing symbolic link at the final destination using a non-following metadata check. 4. Generate the wrapper in a secure temporary file created with `mktemp` inside the target directory. 5. Set the temporary file's permissions before publication, then atomically rename it to the final destination. 6. Define an explicit replacement policy. If replacing an existing wrapper is allowed, verify that the existing object is a regular file with acceptable ownership before replacement. 7. Use a restrictive `umask`, such as `umask 077`, during temporary-file creation. 8. Add tests for existing symlinks, hard links where relevant, filename normalization collisions, attacker-writable target directories, and concurrent installation attempts. A safer installation structure is: ```bash [[ "$NAME" =~ ^[A-Za-z0-9._-]+$ ]] || exit 1 safe_name="$NAME" wrapper="$TARGET_DIR/$safe_name" mkdir -p -- "$TARGET_DIR" [[ ! -L "$wrapper" ]] || { echo "Refusing to replace symbolic link: $wrapper" >&2 exit 1 } umask 077 tmp="$(mktemp "$TARGET_DIR/.${safe_name}.tmp.XXXXXX")" trap 'rm -f -- "$tmp"' EXIT # Write generated wrapper content to "$tmp". chmod 755 -- "$tmp" # Before replacement, verify the destination state and ownership according to # the intended replacement policy. mv -- "$tmp" "$wrapper" trap - EXIT ``` For privileged deployments, directory ownership and permissions should also be validated immediately before the atomic rename to reduce race opportunities. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Ae1

High
Category
analysis-evasion
Content
- `scripts/install-wrapper.sh`: create one SSH wrapper for a remote binary
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill declares shell and file-read capable behavior in its documentation and workflow, but does not define an explicit tool scope such as permissions or allowed-tools. That creates an overbroad execution surface where an agent may invoke shell/file access more freely than intended, which is especially relevant here because the skill installs SSH wrappers, reads local OpenClaw config, and could influence remote command execution paths.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This shell script writes another executable wrapper that will initiate SSH connections, send Wake-on-LAN network packets, and execute a remote binary. Although the generated wrapper logs one failure/retry message, the installer itself does not clearly warn the user that it is creating a script with these network and remote-execution behaviors before writing it to disk.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
EOF
} > "$wrapper"

chmod 755 "$wrapper"
echo "Installed wrapper: $wrapper"
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

No suspicious patterns detected.