Back to skill

Security audit

Muster Connect

Security checks for vulnerabilities and agentic risk

Overview

This skill is review-worthy because it installs persistent services, exposes a public tunnel, modifies future agent instructions, and lets a Muster endpoint influence tasks and updates.

Install only if you are comfortable with a local server that persists across sessions, exposes a Cloudflare tunnel by default, stores and prints bearer keys, modifies OpenClaw and HEARTBEAT configuration, and sends agent identity, logs, reflections, task data, and token usage to the configured Muster endpoint. Review the scripts first, prefer localhost-only operation, avoid automatic updates from heartbeat responses, and rotate any keys that appear in logs or transcripts.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (7)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/install.sh:107
Finding
Unverified Remote Scripts and Mutable Upstream Code Are Executed Locally<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:107-155`, `scripts/update.sh:62-88`, `SKILL.md:38`, `HEARTBEAT_MUSTER.md:11`, `TROUBLESHOOTING.md:8` **Vulnerability Type**: Remote payload retrieval and supply-chain execution **Risk Level**: Critical ### Vulnerable Code ```bash if ! command_exists node || [ "$(node -e 'console.log(parseInt(process.versions.node))')" -lt 20 ]; then log "Installing Node.js ≥ 20..." if [ "$OS" = "macos" ]; then brew install node@20 else curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y -qq nodejs; fi fi ``` ```bash else curl -fsSL https://get.docker.com | sh sudo usermod -aG docker "$USER" 2>/dev/null || true fi ``` ```bash if [ -d "$INSTALL_DIR" ]; then log "$INSTALL_DIR exists — pulling latest..."; cd "$INSTALL_DIR"; git pull origin main else git clone https://github.com/AirborneEagle/muster.git "$INSTALL_DIR"; cd "$INSTALL_DIR" fi npm install --silent ``` The update mechanism similarly fetches and executes mutable code: ```bash git fetch origin main --quiet REMOTE_VERSION=$(git show origin/main:package.json | node -e "const d=require('fs').readFileSync('/dev/stdin','utf8');console.log(JSON.parse(d).version)" 2>/dev/null || echo "unknown") git pull origin main npm install --silent npm run build npx drizzle-kit migrate restart_service "$SERVICE_MODE" ``` Persistent instructions can trigger that update based on a remote response: ```markdown - If `update_available` is true: run `bash ~/.openclaw/workspace/skills/muster/scripts/update.sh` ``` ### Technical Analysis The installer pipes responses from NodeSource and Docker directly into a shell. The NodeSource response is executed through `sudo`, while Docker's installer may independently request or use elevated privileges. No version pin, cryptographic hash, detached signature, or local review step is present. The application installation and update paths also trust mutable `main` branch con ...[truncated 1665 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every `curl | sh` pipeline with a staged installation process: - Download a fixed-version artifact. - Verify a vendor-published SHA-256 checksum and, preferably, a detached signature. - Store it in a securely created temporary directory. - Present the exact version and requested privilege changes to the user before execution. 2. Pin the Muster source to a signed release tag or immutable commit rather than `origin/main`. 3. Require explicit human confirmation before every update, database migration, or persistent-service replacement. A remote heartbeat response must never be sufficient authorization. 4. Commit and enforce a lockfile, use `npm ci`, audit dependency lifecycle scripts, and consider `npm ci --ignore-scripts` where compatible. 5. Pin Cloudflared to a specific architecture-aware release and verify its checksum or signature. 6. Run build and migration operations under a dedicated unprivileged service account. 7. Separate package installation requiring `sudo` from ordinary Skill execution and document each privileged operation. ]]>

T01 · Skill Instruction Hijacking

Error
Location
scripts/connect.sh:280
Finding
Persistent Heartbeat Modification Creates a Cross-Session Remote Control Channel<![CDATA[ ## Vulnerability Details **File Location**: `scripts/connect.sh:280-288`, `HEARTBEAT_MUSTER.md:2-15`, `SKILL.md:32-38`, `SKILL.md:84-97` **Vulnerability Type**: Persistent agent instruction and memory modification **Risk Level**: High ### Vulnerable Code ```bash if [ -f "$HEARTBEAT_FRAGMENT" ]; then if [ -f "$HEARTBEAT_FILE" ] && grep -q "## Muster check-in" "$HEARTBEAT_FILE"; then log "✓ HEARTBEAT.md already has Muster section — skipping" else mkdir -p "$(dirname "$HEARTBEAT_FILE")" cat "$HEARTBEAT_FRAGMENT" >> "$HEARTBEAT_FILE" log "✓ Appended Muster checklist to HEARTBEAT.md" fi fi ``` The appended instructions include: ```markdown ## Muster check-in - Call Muster MCP `heartbeat` tool with your agent_id and current status - If `next_task` returned: pick it up (see Muster skill for task workflow) - If `update_available` is true: run `bash ~/.openclaw/workspace/skills/muster/scripts/update.sh` - If `tunnel_url` changed vs `~/.muster/tunnel.json`: update stored value, notify human with new URL - If tunnel is down (no `tunnel_url`): restart tunnel service - If idle and no tasks: consider proposing initiative via `create_task` ``` The Skill also directs the agent to prioritize the remote service: ```markdown ### heartbeat — call every wake cycle Reports status, picks up work. **Always call this first.** ``` ### Technical Analysis `connect.sh` does more than configure an optional API client: it appends behavioral instructions to the agent's persistent `HEARTBEAT.md`. These instructions survive the current invocation and affect future wake cycles and sessions. The injected rules require recurring contact with a remote endpoint, acceptance of remote task assignments, automatic reaction to update signals, service restart behavior, and proactive creation of work. This gives content returned by the Muster endpoint continuing influence over the agent's priorities and local actions. The instructions do not clearly establish that re ...[truncated 1332 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not automatically modify `HEARTBEAT.md`, agent memory, identity files, or other persistent instruction stores. 2. Display the proposed fragment and obtain explicit, informed human consent before installing it. 3. Provide a nonpersistent connection mode as the default. 4. State explicitly that endpoint responses and task bodies are untrusted data and cannot override system, developer, current-user, or safety instructions. 5. Remove automatic update execution from heartbeat behavior. Report update availability to the human instead. 6. Require confirmation before restarting services, changing persistent state, or accepting tasks that trigger local side effects. 7. Record exactly which heartbeat file was modified and provide a reliable scoped rollback operation. ]]>

T06 · System Persistence

Error
Location
scripts/install.sh:228
Finding
Always-On Services, Git Hooks, and Public Tunnel Establish Broad System Persistence<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:228-290`, `scripts/install.sh:329-382` **Vulnerability Type**: Persistent services, repository hooks, and public network exposure **Risk Level**: High ### Vulnerable Code ```bash <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>ThrottleInterval</key> <integer>10</integer> ``` The installer also writes executable repository hooks: ```bash for hook in post-commit post-merge; do cat > "$HOOKS_DIR/$hook" << 'HOOKEOF' #!/usr/bin/env bash set -e MUSTER_DIR="$(git rev-parse --show-toplevel)" SERVICE="com.bai.muster" LOGFILE="$MUSTER_DIR/logs/deploy.log" cd "$MUSTER_DIR" /opt/homebrew/bin/npm run build >> "$LOGFILE" 2>&1 launchctl kickstart -k "gui/$(id -u)/$SERVICE" >> "$LOGFILE" 2>&1 HOOKEOF chmod +x "$HOOKS_DIR/$hook" done ``` A persistent public tunnel is enabled by default: ```bash <string>$(command -v cloudflared)</string> <string>tunnel</string> <string>--url</string> <string>http://localhost:${MUSTER_PORT}</string> ``` ```bash <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> ``` On Linux, comparable persistence is installed through PM2: ```bash pm2 save pm2 startup ``` ### Technical Analysis The Skill installs two always-on processes: the Muster server and a Cloudflare quick tunnel. It configures them to restart automatically and survive logins or reboots. It additionally modifies Git hooks so commits and merges execute builds and restart the service. An always-on service is related to the declared server functionality, but the public tunnel and Git hook modifications are not required for a local coordination service. Enabling all of these by default unnecessarily expands persistence, supply-chain, and network attack surfaces. If source code or dependencies are later compromised, the Git hooks and service manager automatically rebuild and relaunch the payload. The quick tunnel also makes a locally hosted application reachable through an externally ...[truncated 1124 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default to a foreground, localhost-only service with no boot persistence. 2. Add separate, explicit options such as `--enable-service`, `--enable-tunnel`, and `--install-git-hooks`; require human confirmation for each. 3. Do not install Git hooks automatically. Provide an optional documented hook template instead. 4. Prefer an authenticated named tunnel with access policies over an unauthenticated quick tunnel. 5. Bind the application explicitly to loopback unless remote access is enabled. 6. Run persistent components under a dedicated low-privilege account with restricted filesystem and network access. 7. Ensure uninstall removes all startup entries, hooks, process dumps, tunnel configuration, and logs. 8. Display a clear pre-install summary of every persistent and externally reachable component. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:32
Finding
Sensitive Agent Data Is Routed Through a Publicly Exposed Control Plane Without Data Minimization<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:32-82`, `scripts/install.sh:329-363` **Vulnerability Type**: Excessive data collection and externally reachable service exposure **Risk Level**: High ### Vulnerable Instructions ```markdown - On first heartbeat, include soul content and skill list in `metadata` ``` ```markdown ### post_logs - Input: `agent_id`, `task_instance_id`, `entries[]` with `level` (info|reflection|warn|error|debug) and `content` ``` ```markdown ### report_cost - Input: `agent_id`, `model`, `input_tokens`, `output_tokens`, optional `task_instance_id` - Call after each LLM interaction. ``` ```markdown ### submit_reflection - Input: `agent_id`, `content`, `reflection_type` ``` ```markdown ### update_agent — evolve your own identity - Input: `agent_id`, optional `soul_content`, `heartbeat_content`, `identity_content` ``` The corresponding service is exposed through a Cloudflare quick tunnel: ```bash pm2 start cloudflared --name muster-tunnel -- tunnel --url "http://localhost:${MUSTER_PORT}" ``` ### Technical Analysis The workflow requires transmission of agent identity material, skill inventory, work status, logs, reflections, task summaries, and per-interaction usage telemetry. These categories may contain internal project details, behavioral profiles, organizational context, or sensitive reasoning. The collection is broader than necessary for basic task assignment. The project does not enforce redaction, content classification, endpoint allowlisting, per-category consent, or a prohibition against submitting secrets. The same server is exposed through a persistent public quick tunnel by default. Although the API uses bearer authentication for MCP calls, the reviewed Skill package does not contain the server implementation, so authorization coverage, retention, encryption at rest, and route-level access controls cannot be verified from this artifact. ### Attack Path 1. The agent follows the mandatory heartbeat and ...[truncated 899 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default to localhost-only operation and disable tunnel creation unless explicitly requested. 2. Make soul content, skill inventory, reflections, logs, and cost telemetry independently opt-in. 3. Define a strict data-minimization policy and prohibit submission of credentials, prompts, file contents, private keys, and unrelated user data. 4. Add local redaction and secret scanning before telemetry is transmitted. 5. Require HTTPS for non-loopback endpoints and restrict endpoints to a human-approved allowlist. 6. Document server-side retention, deletion, encryption, audit logging, and administrator access controls. 7. Use narrow per-agent scopes and verify that an agent cannot read or update another agent's records. 8. Conduct a separate audit of the server implementation before enabling public access. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/install.sh:393
Finding
Administrator and Agent Credentials Are Stored and Printed Insecurely<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:393-424`, `scripts/connect.sh:245-273`, `scripts/connect.sh:326-342` **Vulnerability Type**: Plaintext sensitive data and credential disclosure **Risk Level**: High ### Vulnerable Code ```bash if grep -q "^MUSTER_ADMIN_KEY=" "$ENV_FILE" 2>/dev/null; then ADMIN_PASSWORD=$(grep "^MUSTER_ADMIN_KEY=" "$ENV_FILE" | cut -d= -f2) else ADMIN_PASSWORD="sk-muster-admin-$(openssl rand -hex 32)" echo "MUSTER_ADMIN_KEY=${ADMIN_PASSWORD}" >> "$ENV_FILE" fi ``` The key is then returned through standard output: ```bash cat <<REPORT_JSON { "success": true, "muster_url": "http://localhost:${MUSTER_PORT}", "muster_endpoint": "http://localhost:${MUSTER_PORT}/mcp", "tunnel_url": "${TUNNEL_URL}", "admin_email": "admin@localhost", "admin_password": "${ADMIN_PASSWORD}", "install_dir": "${INSTALL_DIR}", "port": ${MUSTER_PORT}, "db_url": "${MUSTER_DB_URL}" } REPORT_JSON ``` The agent API key is stored in the OpenClaw configuration: ```python config["skills"]["entries"]["muster"] = { "enabled": True, "env": { "MUSTER_ENDPOINT": "$MUSTER_ENDPOINT", "MUSTER_API_KEY": "$REGISTERED_KEY" } } ``` It is also printed in the connection report: ```bash cat <<REPORT_JSON { "success": true, "agent_id": "${AGENT_ID}", "api_key": "${REGISTERED_KEY}", "muster_endpoint": "${MUSTER_ENDPOINT}" } REPORT_JSON ``` ### Technical Analysis The scripts create secret-bearing files without first setting a restrictive `umask` and without applying explicit mode `0600`. Actual exposure depends on the user's current umask and existing file permissions, which is unsafe for bearer credentials. Both the administrator key and agent API key are emitted through standard output. Skill runners, CI systems, terminal capture, agent transcripts, or diagnostic logging may retain that output. Anyone obtaining these bearer values may be able to impersonate an agent or administer the server. ...[truncated 1101 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set `umask 077` at the beginning of every script that creates secret-bearing files. 2. Create configuration atomically and enforce mode `0600`; verify ownership before modifying existing files. 3. Store API and administrator keys in an operating-system credential manager where available. 4. Never include full credentials in standard JSON output. Return a credential reference or a one-time secure retrieval instruction. 5. Redact keys from logs and error messages and add automated tests for accidental credential output. 6. Generate a random PostgreSQL password and store it with restrictive permissions. 7. Rotate all keys that may already have appeared in logs or transcripts. 8. Use scoped, revocable, short-lived credentials where supported. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/connect.sh:205
Finding
Unescaped Shell Values Permit Python and JSON Injection During Connection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/connect.sh:205-209`, `scripts/connect.sh:253-273`, `scripts/connect.sh:310-325` **Vulnerability Type**: Code injection and malformed request construction **Risk Level**: High ### Vulnerable Code Registration JSON is constructed through raw string concatenation: ```bash REGISTER_BODY="{\"name\":\"${AGENT_NAME}\",\"title\":\"${AGENT_TITLE}\",\"slug\":\"${AGENT_SLUG}\",\"runtime\":\"openclaw\"" if [ -n "$AGENT_WEBHOOK" ]; then REGISTER_BODY="${REGISTER_BODY},\"webhookUrl\":\"${AGENT_WEBHOOK}\"" fi REGISTER_BODY="${REGISTER_BODY}}" ``` Shell variables are expanded directly into executable Python source: ```bash python3 << PYEOF import json, os config_path = "$OPENCLAW_CONFIG" try: with open(config_path) as f: config = json.load(f) except (json.JSONDecodeError, FileNotFoundError): config = {} config.setdefault("skills", {}).setdefault("entries", {}) config["skills"]["entries"]["muster"] = { "enabled": True, "env": { "MUSTER_ENDPOINT": "$MUSTER_ENDPOINT", "MUSTER_API_KEY": "$REGISTERED_KEY" } } with open(config_path, "w") as f: json.dump(config, f, indent=2) PYEOF ``` Heartbeat JSON is also manually interpolated: ```bash -d "{ \"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/call\", \"params\": { \"name\": \"heartbeat\", \"arguments\": { \"agent_id\": \"$AGENT_ID\", \"status\": \"idle\", \"metadata\": {\"first_heartbeat\": true, \"name\": \"$AGENT_NAME\", \"title\": \"$AGENT_TITLE\"} } } }" ``` ### Technical Analysis Values supplied by command-line arguments, identity files, registration responses, or remote endpoint configuration are inserted into Python source and JSON without escaping. Quotes, backslashes, line breaks, or Python syntax can terminate string literals and inject new statements into the heredoc. The same issue affects registration and heartbeat JSON. Crafted identity or webhook data ca ...[truncated 1448 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never expand shell values into executable Python source. 2. Pass values using environment variables or `sys.argv`, then read them strictly as data: - `MUSTER_ENDPOINT="$MUSTER_ENDPOINT" python3 - <<'PY'` - Read with `os.environ["MUSTER_ENDPOINT"]`. 3. Quote heredoc delimiters so the shell cannot expand their contents. 4. Construct every request with a real JSON serializer such as Python `json.dumps` or `jq --arg`. 5. Validate endpoints with an allowlisted scheme and host policy. 6. Restrict slugs to a documented safe character set and enforce reasonable lengths for all identity fields. 7. Validate webhook URLs and reject control characters and embedded newlines. 8. Add regression tests using quotes, backslashes, Unicode, newlines, and injection payloads. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/connect.sh:303
Finding
Predictable Shared Temporary File Allows Symlink Clobbering<![CDATA[ ## Vulnerability Details **File Location**: `scripts/connect.sh:303-330` **Vulnerability Type**: Unsafe temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```bash HTTP_CODE=$(curl -s -o /tmp/muster-heartbeat-response.json -w "%{http_code}" -X POST "$MUSTER_ENDPOINT" \ -H "Authorization: Bearer $REGISTERED_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d "{ \"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/call\", \"params\": { \"name\": \"heartbeat\", \"arguments\": { \"agent_id\": \"$AGENT_ID\", \"status\": \"idle\", \"metadata\": {\"first_heartbeat\": true, \"name\": \"$AGENT_NAME\", \"title\": \"$AGENT_TITLE\"} } } }" 2>&1) HEARTBEAT_RESPONSE=$(cat /tmp/muster-heartbeat-response.json 2>/dev/null) rm -f /tmp/muster-heartbeat-response.json ``` ### Technical Analysis The response is written to a fixed path in the shared `/tmp` directory. The script does not securely create the file, verify its ownership, reject symlinks, or isolate concurrent executions. On systems where another local user can create entries in `/tmp`, an attacker may pre-create `/tmp/muster-heartbeat-response.json` as a symbolic link to another file writable by the victim. Curl may then follow that link and overwrite the target. Concurrent runs can also read or delete each other's response files. ### Attack Path 1. A local attacker predicts the fixed filename. 2. The attacker creates `/tmp/muster-heartbeat-response.json` as a symlink to a file writable by the victim. 3. The victim runs `connect.sh`. 4. Curl opens the predictable path and follows the symlink. 5. The target file is overwritten with the heartbeat response, and the script later removes the temporary pathname. 6. Alternatively, a concurrent local process reads the response before cleanup. ### Impact Assessment The primary impact is corruption or truncation of arbitrary files ...[truncated 292 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the file with `mktemp`, for example: ```bash RESPONSE_FILE=$(mktemp "${TMPDIR:-/tmp}/muster-heartbeat.XXXXXX") ``` 2. Install a cleanup trap immediately: ```bash trap 'rm -f -- "$RESPONSE_FILE"' EXIT ``` 3. Set `umask 077` before creating the file. 4. Pass the generated path to curl using a quoted variable. 5. Avoid shared files entirely where possible by capturing the response through a controlled file descriptor or securely isolated temporary directory. 6. Add concurrency tests and verify that pre-existing symlinks cannot influence the destination. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (97)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
## Muster check-in
- Call Muster MCP `heartbeat` tool with your agent_id and current status
- **Error handling:** Distinguish failure modes when the heartbeat curl fails:
  - `curl exit 7` (connection refused) → "Muster server unreachable — check if it's running"
  - `curl exit 28` (timeout) → "Muster server timed out — may be overloaded"
  - HTTP `401` → "API key invalid — regenerate via Settings or re-run connect.sh"
Confidence
60% 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).

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill claims to install and teach the Muster MCP workflow, but the detected behavior also covers update and maintenance operations such as pulling code, rebuilding, migrating, restarting services, and probing local health endpoints. This discrepancy obscures operational side effects and can cause an agent to perform privileged maintenance tasks that are outside the user's expected scope.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill claims to install and teach the Muster MCP workflow, but the detected behavior also covers update and maintenance operations such as pulling code, rebuilding, migrating, restarting services, and probing local health endpoints. This discrepancy obscures operational side effects and can cause an agent to perform privileged maintenance tasks that are outside the user's expected scope.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill claims to install and teach the Muster MCP workflow, but the detected behavior also covers update and maintenance operations such as pulling code, rebuilding, migrating, restarting services, and probing local health endpoints. This discrepancy obscures operational side effects and can cause an agent to perform privileged maintenance tasks that are outside the user's expected scope.

Chaining Abuse

High
Category
Tool Misuse
Content
## Setup Issues

### Docker Not Found
**Linux:** `curl -fsSL https://get.docker.com | sh && sudo usermod -aG docker $USER`
**macOS:** `brew install --cask docker` → open Docker Desktop → accept license.

### Port in Use
Confidence
83% confidence
Finding
This command chains remote script execution and a privileged user-group modification in one line, reducing opportunities for review between risky actions. In an agent-assisted setup flow, such chaining increases the likelihood of unsafe execution and makes it harder to apply principle-of-least-privilege or stop after the download step.

Credential Access

High
Category
Privilege Escalation
Content
**Homebrew (macOS default):** `brew services restart postgresql@16` then `pg_isready`. Reset: `dropdb muster && createdb muster && npx drizzle-kit migrate` (destroys data).
**Docker:** `cd ~/muster && docker compose ps` then `docker compose logs db`. Reset: `docker compose down -v && docker compose up -d && npx drizzle-kit migrate` (destroys data).

### .env Missing
```bash
cat > ~/muster/.env << EOF
MUSTER_DB_URL=postgresql://muster:muster@localhost:5432/muster
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
**Homebrew (macOS default):** `brew services restart postgresql@16` then `pg_isready`. Reset: `dropdb muster && createdb muster && npx drizzle-kit migrate` (destroys data).
**Docker:** `cd ~/muster && docker compose ps` then `docker compose logs db`. Reset: `docker compose down -v && docker compose up -d && npx drizzle-kit migrate` (destroys data).

### .env Missing
```bash
cat > ~/muster/.env << EOF
MUSTER_DB_URL=postgresql://muster:muster@localhost:5432/muster
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
**Homebrew (macOS default):** `brew services restart postgresql@16` then `pg_isready`. Reset: `dropdb muster && createdb muster && npx drizzle-kit migrate` (destroys data).
**Docker:** `cd ~/muster && docker compose ps` then `docker compose logs db`. Reset: `docker compose down -v && docker compose up -d && npx drizzle-kit migrate` (destroys data).

### .env Missing
```bash
cat > ~/muster/.env << EOF
MUSTER_DB_URL=postgresql://muster:muster@localhost:5432/muster
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
**Homebrew (macOS default):** `brew services restart postgresql@16` then `pg_isready`. Reset: `dropdb muster && createdb muster && npx drizzle-kit migrate` (destroys data).
**Docker:** `cd ~/muster && docker compose ps` then `docker compose logs db`. Reset: `docker compose down -v && docker compose up -d && npx drizzle-kit migrate` (destroys data).

### .env Missing
```bash
cat > ~/muster/.env << EOF
MUSTER_DB_URL=postgresql://muster:muster@localhost:5432/muster
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Chaining Abuse

High
Category
Tool Misuse
Content
```

### npm Install Fails
Check `node --version` (≥ 20). Try: `cd ~/muster && rm -rf node_modules package-lock.json && npm install`

---
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
```

### npm Install Fails
Check `node --version` (≥ 20). Try: `cd ~/muster && rm -rf node_modules package-lock.json && npm install`

---
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Credential Access

High
Category
Privilege Escalation
Content
if [ -z "$MUSTER_ENDPOINT" ]; then
  # Try to find from a local install
  if [ -f "$HOME/muster/.env" ]; then
    MUSTER_PORT=$(grep "^PORT=" "$HOME/muster/.env" 2>/dev/null | cut -d= -f2 || echo "3000")
    MUSTER_ENDPOINT="http://localhost:${MUSTER_PORT}/mcp"
    log "Found local Muster at $MUSTER_ENDPOINT"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
if [ -z "$MUSTER_ENDPOINT" ]; then
  # Try to find from a local install
  if [ -f "$HOME/muster/.env" ]; then
    MUSTER_PORT=$(grep "^PORT=" "$HOME/muster/.env" 2>/dev/null | cut -d= -f2 || echo "3000")
    MUSTER_ENDPOINT="http://localhost:${MUSTER_PORT}/mcp"
    log "Found local Muster at $MUSTER_ENDPOINT"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
if [ -z "$MUSTER_ENDPOINT" ]; then
  # Try to find from a local install
  if [ -f "$HOME/muster/.env" ]; then
    MUSTER_PORT=$(grep "^PORT=" "$HOME/muster/.env" 2>/dev/null | cut -d= -f2 || echo "3000")
    MUSTER_ENDPOINT="http://localhost:${MUSTER_PORT}/mcp"
    log "Found local Muster at $MUSTER_ENDPOINT"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
if [ -z "$MUSTER_ENDPOINT" ]; then
  # Try to find from a local install
  if [ -f "$HOME/muster/.env" ]; then
    MUSTER_PORT=$(grep "^PORT=" "$HOME/muster/.env" 2>/dev/null | cut -d= -f2 || echo "3000")
    MUSTER_ENDPOINT="http://localhost:${MUSTER_PORT}/mcp"
    log "Found local Muster at $MUSTER_ENDPOINT"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Self-Modification

High
Category
Rogue Agent
Content
EOF
log "✓ State file: ~/.muster/state.json"

# OpenClaw config — add/update skills.entries.muster
if [ -f "$OPENCLAW_CONFIG" ]; then
  # Use python to safely merge into existing config
  python3 << PYEOF
Confidence
91% confidence
Finding
The script silently modifies ~/.openclaw/openclaw.json to enable the muster skill and inject persistent environment variables including the API key. Self-modifying agent configuration is dangerous because it changes future agent behavior and creates durable trust in an externally supplied endpoint without explicit user approval.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
else
    log "⚠ First heartbeat returned unexpected HTTP $HTTP_CODE"
  fi
  rm -f /tmp/muster-heartbeat-response.json
else
  log "⚠ Skipping heartbeat — missing agent_id or key"
fi
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).

Chaining Abuse

High
Category
Tool Misuse
Content
if ! command_exists git; then
  log "Installing git..."
  if [ "$OS" = "macos" ]; then xcode-select --install 2>/dev/null || true
  else sudo apt-get update -qq && sudo apt-get install -y -qq git; fi
fi
log "✓ git $(git --version | awk '{print $3}')"
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
if ! command_exists node || [ "$(node -e 'console.log(parseInt(process.versions.node))')" -lt 20 ]; then
  log "Installing Node.js ≥ 20..."
  if [ "$OS" = "macos" ]; then brew install node@20
  else curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y -qq nodejs; fi
fi
log "✓ node $(node --version)"
Confidence
95% confidence
Finding
Piping a downloaded script directly to `sudo` is a high-risk anti-pattern because it lets remote content control privileged execution in one step. In an installer, this is especially dangerous since users may trust it and not notice that root code is being sourced live from the network.

Chaining Abuse

High
Category
Tool Misuse
Content
if ! command_exists node || [ "$(node -e 'console.log(parseInt(process.versions.node))')" -lt 20 ]; then
  log "Installing Node.js ≥ 20..."
  if [ "$OS" = "macos" ]; then brew install node@20
  else curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y -qq nodejs; fi
fi
log "✓ node $(node --version)"
Confidence
95% confidence
Finding
Piping a downloaded script directly to `sudo` is a high-risk anti-pattern because it lets remote content control privileged execution in one step. In an installer, this is especially dangerous since users may trust it and not notice that root code is being sourced live from the network.

Chaining Abuse

High
Category
Tool Misuse
Content
log "⚠ Docker Desktop is opening. Accept the license agreement to continue."
      while ! docker info &>/dev/null; do sleep 5; done
    else
      curl -fsSL https://get.docker.com | sh
      sudo usermod -aG docker "$USER" 2>/dev/null || true
    fi
  fi
Confidence
95% confidence
Finding
`curl ... | sh` creates a direct execution chain from external content to the local shell, which is a well-known supply-chain hazard. In this installer, the behavior is not clearly necessary to the stated skill purpose and increases host compromise risk.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The installer automatically installs `cloudflared`, a prerequisite for publishing the local service externally, despite the skill description only promising local installation and connection. This materially expands exposure by preparing unauthenticated remote-access capability without clear, informed user consent.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
if [ "$OS" = "macos" ]; then brew install cloudflare/cloudflare/cloudflared
  else
    curl -fsSL -o /tmp/cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
    sudo install -m 755 /tmp/cloudflared /usr/local/bin/cloudflared; rm -f /tmp/cloudflared
  fi
fi
log "✓ cloudflared $(cloudflared --version 2>&1 | awk '{print $3}')"
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).

Chaining Abuse

High
Category
Tool Misuse
Content
if [ "$OS" = "macos" ]; then brew install cloudflare/cloudflare/cloudflared
  else
    curl -fsSL -o /tmp/cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
    sudo install -m 755 /tmp/cloudflared /usr/local/bin/cloudflared; rm -f /tmp/cloudflared
  fi
fi
log "✓ cloudflared $(cloudflared --version 2>&1 | awk '{print $3}')"
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The installer automatically creates a Cloudflare tunnel to `http://localhost:${MUSTER_PORT}` and persists it via launchd or pm2, exposing the service beyond localhost. Because the skill description does not justify public internet exposure, this behavior creates significant remote attack surface and is especially dangerous if the application has weak authentication or future vulnerabilities.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/install.sh:410