Back to skill

Security audit

Mac Node Bridge

Security checks for vulnerabilities and agentic risk

Overview

The skill openly creates SSH wrappers for Mac tools, but its shell scripts have input-validation flaws that could let crafted host or path values run unintended commands.

Install only if you fully trust the host, path, key, and known-hosts values being supplied and are comfortable granting this gateway remote access to Mac-side tools. Before wider use, the scripts should validate SSH destinations, safely serialize generated wrapper configuration, avoid concatenating paths into remote shell strings, and warn before overwriting existing wrapper files.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/install-wrapper.sh:57
Finding
Shell Code Injection in Generated SSH Wrapper<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install-wrapper.sh:57-76` **Vulnerability Type**: Shell code injection through unsafe script generation **Risk Level**: High ### 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 an absolute path" >&2; exit 1; } mkdir -p "$TARGET_DIR" wrapper="$TARGET_DIR/$safe_name" ssh_opts=() if [[ -n "$SSH_KEY" ]]; then ssh_opts+=("-i" "$SSH_KEY" "-o" "IdentitiesOnly=yes") fi if [[ -n "$KNOWN_HOSTS" ]]; then ssh_opts+=("-o" "UserKnownHostsFile=$KNOWN_HOSTS") fi cat > "$wrapper" <<EOF #!/usr/bin/env bash set -euo pipefail remote_cmd=\$(printf '%q ' "$REMOTE_BIN" "\$@") exec ssh ${ssh_opts[*]:-} -T "$HOST" "bash -lc \$remote_cmd" EOF ``` ### Technical Analysis The installer generates an executable Bash script using an unquoted heredoc. Values including `REMOTE_BIN`, `HOST`, `SSH_KEY`, and `KNOWN_HOSTS` are inserted directly into the generated shell source without shell-safe serialization. The only validation applied to `REMOTE_BIN` requires it to begin with `/`. It does not reject quotation marks, command substitutions, newlines, backticks, or other shell syntax. `HOST`, `SSH_KEY`, and `KNOWN_HOSTS` receive no equivalent syntax validation. Consequently, a crafted value can break out of its intended syntactic position in the generated wrapper. The malicious syntax is persisted in the wrapper and can execute locally when that wrapper is subsequently invoked. The array used while running the installer does not protect the generated script because `${ssh_opts[*]}` flattens the options into source text. Quoting information from the original array is therefore lost. ### Attack Path 1. An attacker influences an installation argument such as `--remote-bin`, `--host`, `--ssh-key`, or `--known-hosts`. 2. The value satisfies the limited validation. For exa ...[truncated 998 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not interpolate configuration values into executable shell source. - Generate the wrapper from a single-quoted static template and load configuration from a separately created, permission-restricted file. - If values must be embedded, serialize every value with `printf '%q'` before writing it to the wrapper. - Preserve SSH options as a Bash array inside the generated wrapper rather than expanding an installer-side array with `${ssh_opts[*]}`. - Validate `HOST` against an explicit `USER@HOST` or approved SSH alias format. - Require path arguments to be absolute, reject control characters and newlines, and resolve or normalize them where appropriate. - Reject unexpected shell metacharacters in fields that do not legitimately require them. - Write wrappers atomically using a temporary file created in the destination directory, set secure permissions, and then rename the file into place. - Consider installing wrappers with mode `0750` or stricter when they expose sensitive remote capabilities. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verify-node-tool.sh:91
Finding
Remote Command Injection in Explicit Binary Verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/verify-node-tool.sh:91-93` **Vulnerability Type**: Remote shell command injection **Risk Level**: Medium ### Vulnerable Code ```bash [[ "$REMOTE_BIN" = /* ]] || { echo "bin must be an absolute path" >&2; exit 1; } ssh -T "$HOST" "test -x '$REMOTE_BIN' && printf 'OK %s\n' '$REMOTE_BIN' || { printf 'MISSING %s\n' '$REMOTE_BIN' >&2; exit 1; }" ``` ### Technical Analysis `REMOTE_BIN` is concatenated into a command string that is interpreted by the remote login shell. Although the value is surrounded by single quotes, embedded single quotes are neither rejected nor escaped. The absolute-path check only verifies that the first character is `/`. A crafted value can begin with `/`, terminate the single-quoted string, add shell operators and commands, and then restore syntactic validity. Local quoting of `"$HOST"` and the overall command argument does not protect the value after SSH sends the constructed string for remote shell evaluation. This differs from passing user-controlled data as positional parameters to a fixed script. Here, data and remote shell syntax are combined in the same string. ### Attack Path 1. An attacker influences the value passed through `--bin`. 2. The supplied value starts with `/`, passing the absolute-path check. 3. The value contains a single quote followed by shell syntax. 4. The script concatenates that value into the SSH command string. 5. SSH sends the resulting command to the configured Mac node. 6. The remote login shell interprets the injected syntax. 7. The attacker's command executes as the configured remote SSH user. ### Impact Assessment Successful exploitation permits arbitrary command execution on the target Mac node under the configured SSH account. The attacker can read or modify files accessible to that account, invoke macOS tools for which the account has privacy permissions, alter user-level configuration, or compromise credentials available in that u ...[truncated 226 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not concatenate `REMOTE_BIN` into a remote shell command. - Pass the path as a positional argument to a fixed remote script, following the safer pattern already used by `resolve_remote_tool`. - A suitable design is to invoke a fixed script through `bash -s -- "$REMOTE_BIN"` and reference the supplied path as `"$1"` inside that script. - Alternatively, serialize the value using a proven shell-escaping mechanism before including it in a command string, though positional arguments are preferable. - Reject newline, carriage-return, NUL-equivalent, and other control characters. - Retain the absolute-path requirement and consider restricting verification to approved directory prefixes when the deployment model permits it. - Add regression tests using paths containing spaces, single quotes, double quotes, dollar signs, command substitutions, semicolons, and newlines. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/install-preset.sh:71
Finding
Unvalidated SSH Destination Can Be Interpreted as SSH Options<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install-preset.sh:71` **Additional Locations**: `scripts/verify-node-tool.sh:52,93`; `scripts/install-wrapper.sh:76` **Vulnerability Type**: SSH option injection **Risk Level**: Medium ### Vulnerable Code ```bash if ! ssh -T "$host" bash -lc "$(printf '%q' "$remote_script")" -- "$tool" "$brew_prefix"; then ``` Equivalent unvalidated destination handling also appears in the verification script: ```bash ssh -T "$host" bash -lc "$(printf '%q' "$remote_script")" -- "$tool" "$brew_prefix" ``` ```bash ssh -T "$HOST" "test -x '$REMOTE_BIN' && printf 'OK %s\n' '$REMOTE_BIN' || { printf 'MISSING %s\n' '$REMOTE_BIN' >&2; exit 1; }" ``` The generated wrapper uses the same pattern: ```bash exec ssh ${ssh_opts[*]:-} -T "$HOST" "bash -lc \$remote_cmd" ``` ### Technical Analysis Shell quoting preserves each host value as one argument, but it does not prevent the SSH client from interpreting an argument beginning with `-` as an option. The scripts do not validate that the supplied host is a legitimate `USER@HOST` value or approved SSH alias, and they do not explicitly terminate SSH option parsing before the destination. A malicious destination may therefore inject SSH client options. Depending on the installed SSH client and supplied options, this can modify configuration loading, host-key handling, identity selection, or proxy behavior. Options such as a crafted proxy command can cause local command execution when SSH attempts to establish the connection. This issue is independently present during preset resolution and verification. It is also propagated into generated wrappers by the unsafe source generation identified separately. ### Attack Path 1. An attacker controls or influences a `--host` argument. 2. The attacker provides a value beginning with `-` that the SSH client recognizes as an option. 3. The shell passes the value as one argument, but SSH processes it as configuration rather than as ...[truncated 832 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Strictly validate host input before invoking SSH. - Reject values beginning with `-`, values containing whitespace or control characters, and values that do not match an approved `USER@HOST`, hostname, IP address, or configured alias format. - Use an SSH option terminator before the destination where supported by the target SSH implementation. - Prefer an allowlist of configured node aliases when the set of Mac nodes is known. - Build all SSH invocations from arrays so each option and value remains a distinct argument. - Do not permit callers to supply arbitrary SSH option fragments through host or path fields. - Apply the same validation consistently in `install-preset.sh`, `verify-node-tool.sh`, and `install-wrapper.sh`. - Add tests confirming that host values beginning with `-` are rejected before SSH is executed. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Ae1

High
Category
analysis-evasion
Content
scripts/verify-node-tool.sh --host agent1@mac-mini.local --tool imsg
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/verify-node-tool.sh --host agent1@mac-mini.local --tool imsg
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/verify-node-tool.sh --host agent1@mac-mini.local --tool imsg
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/verify-node-tool.sh --host agent1@mac-mini.local --tool imsg
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/install-preset.sh \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/install-preset.sh \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/install-preset.sh \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/install-preset.sh \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/install-preset.sh \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/install-preset.sh \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill clearly instructs users to run shell scripts and install SSH-based wrappers, but the manifest does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization gap: consumers and reviewers cannot tell from metadata that the skill is intended to invoke shell capabilities and remote execution over SSH, increasing the chance of overbroad or unintended execution.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
exec ssh ${ssh_opts[*]:-} -T "$HOST" "bash -lc \$remote_cmd"
EOF

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.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script initiates an SSH session and executes a remote bash command on the target host, which is a safety-relevant operation under the code-file warning criteria. While the usage text describes the script's purpose, there is no explicit warning, confirmation, or user-facing disclosure at the execution point that a remote command will be run on the specified host.

Missing User Warnings

Low
Confidence
78% confidence
Finding
This code creates a target directory, writes a new executable file, and changes its permissions. Although the usage text says it 'creates a small wrapper script,' there is no explicit in-flow confirmation prompt or caution that an existing file at the target path may be overwritten.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This line performs a remote shell command over SSH to test executability of a path on another machine. Although the operation is limited, it is still subprocess-style remote execution and the script does not provide an explicit warning or confirmation at the point of action beyond generic usage text.

Static analysis

No suspicious patterns detected.