T09 · Insecure Skill Coding Practices
- Location
scripts/setup.sh:347- Finding
Root Command Execution Through Unsafe API-Key Interpolation
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
Clack’s voice relay purpose is clear, but its installer and service use broad root-level persistence and under-scoped network/authentication controls that need review before installation.
Install only after reviewing the scripts and preferably on a dedicated host. Avoid multi-user machines, restrict firewall and Tailscale ACLs tightly, protect and rotate relay/gateway tokens, and be cautious with clack update until the service runs under an unprivileged account with pinned dependencies and implemented rate limits.
scripts/setup.sh:347Root Command Execution Through Unsafe API-Key Interpolation
scripts/setup.sh:367User-Modifiable Skill Code Is Persistently Executed as Root
scripts/clack.sh:27Unverified Mutable Updates Are Immediately Activated by a Privileged Service
server.py:977Public Pairing Endpoint Lacks the Documented Brute-Force Protections
server.py:593All Clients in the Tailscale Address Range Bypass Application Authentication
server.py:1241Unbounded WebSocket Audio Buffer Permits Memory Exhaustion
scripts/setup.sh:361Long-Lived Authentication Secrets Are Embedded in Service Files and URL Query Strings
scripts/setup.sh:189Privileged Setup Installs Unpinned Python Dependencies
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
## 1.5.3 (2026-02-26)
### Security
- **Tailscale APT install**: Replaced `curl | sh` with official APT repository for Tailscale installation
- **Context sanitization**: User context is stripped to natural-language characters only (letters, numbers, common punctuation). IP addresses and domains are removed. Capped at 1000 characters.
- **Provider keys in config.json**: API keys stored in `config.json` (chmod 600) instead of systemd environment variables
The skill markets itself primarily as deployment/management for a relay server, but it also includes uninstall behavior and privileged modification/removal of system files and services. That gap is risky because destructive system changes may be triggered under a benign-sounding skill description, especially in an agent context where users may not expect service removal or config deletion.
The skill markets itself primarily as deployment/management for a relay server, but it also includes uninstall behavior and privileged modification/removal of system files and services. That gap is risky because destructive system changes may be triggered under a benign-sounding skill description, especially in an agent context where users may not expect service removal or config deletion.
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).
Context is sanitized before saving — only natural-language characters are kept (letters, numbers, common punctuation). IP addresses and domains are stripped. The server returns the sanitized text in the response so the app can show the user exactly what will be sent as context.
Context persists across calls and server restarts. Clear it via `DELETE /context` or by sending an empty `set_context` message.
## Conversation History
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).
Context is sanitized before saving — only natural-language characters are kept (letters, numbers, common punctuation). IP addresses and domains are stripped. The server returns the sanitized text in the response so the app can show the user exactly what will be sent as context.
Context persists across calls and server restarts. Clear it via `DELETE /context` or by sending an empty `set_context` message.
## Conversation History
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).
- **Max messages:** 50 (configurable via `CLACK_MAX_HISTORY`)
- History persists across calls and server restarts
- Viewable via `GET /history`, clearable via `DELETE /history`
## Echo Test Mode
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).
- **Max messages:** 50 (configurable via `CLACK_MAX_HISTORY`)
- History persists across calls and server restarts
- Viewable via `GET /history`, clearable via `DELETE /history`
## Echo Test Mode
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
| `GET /voices` | GET | Yes | List available TTS voices |
| `GET /sessions` | GET | Yes | List active sessions |
| `GET /history` | GET | Yes | Get conversation history |
| `DELETE /history` | DELETE | Yes | Clear conversation history |
| `GET /context` | GET | Yes | Get current user context |
| `PUT /context` | PUT | Yes | Set user context (query param `text`) |
| `POST /context` | POST | Yes | Set user context (JSON body `{"text": "..."}`) |
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
fi
# Generate pairing code
RESPONSE=$(curl -s "http://localhost:${PORT}/pair?token=${RELAY_AUTH_TOKEN}")
CODE=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['code'])" 2>/dev/null)
if [[ -z "$CODE" ]]; then
The service accepts a client-supplied systemPrompt and uses it as the session’s top-level instruction, allowing any client to redefine safeguards and behavior. This defeats the server’s own protective prompt and makes jailbreaks, unsafe actions, and policy bypass straightforward.
Untrusted context text is concatenated directly into the system prompt, giving user-supplied content system-level influence over downstream model behavior. In a voice-agent bridge, this can subvert safety rules, bias decisions, exfiltrate retained information, or manipulate future sessions because the context is also persisted.
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
session.update_context(ctx_text)
await session.send_json({"type": "context_updated", "text": ctx_text})
else:
# Clear context
session.user_context = {}
if CONTEXT_FILE.exists():
CONTEXT_FILE.unlink()
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
session.update_context(ctx_text)
await session.send_json({"type": "context_updated", "text": ctx_text})
else:
# Clear context
session.user_context = {}
if CONTEXT_FILE.exists():
CONTEXT_FILE.unlink()
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
if ! command -v tailscale &>/dev/null; then
echo ""
echo "Installing Tailscale via APT..."
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | tee /etc/apt/sources.list.d/tailscale.list >/dev/null
apt-get update -qq
apt-get install -y -qq tailscale > /dev/null 2>&1
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
if ! command -v tailscale &>/dev/null; then
echo ""
echo "Installing Tailscale via APT..."
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | tee /etc/apt/sources.list.d/tailscale.list >/dev/null
apt-get update -qq
apt-get install -y -qq tailscale > /dev/null 2>&1
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
if ! command -v tailscale &>/dev/null; then
echo ""
echo "Installing Tailscale via APT..."
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | tee /etc/apt/sources.list.d/tailscale.list >/dev/null
apt-get update -qq
apt-get install -y -qq tailscale > /dev/null 2>&1
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
if ! command -v tailscale &>/dev/null; then
echo ""
echo "Installing Tailscale via APT..."
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | tee /etc/apt/sources.list.d/tailscale.list >/dev/null
apt-get update -qq
apt-get install -y -qq tailscale > /dev/null 2>&1
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).
echo "Stopping clack service..."
systemctl stop clack 2>/dev/null || true
systemctl disable clack 2>/dev/null || true
rm -f /etc/systemd/system/clack.service
systemctl daemon-reload
echo " ✓ Service removed"
else
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).
# Remove CLI symlink
if [[ -L /usr/local/bin/clack ]]; then
rm -f /usr/local/bin/clack
echo " ✓ 'clack' command removed"
fi
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).
# Remove venv
if [[ -d "$SKILL_DIR/venv" ]]; then
rm -rf "$SKILL_DIR/venv"
echo " ✓ Python venv removed"
fi
The authentication logic allows unauthenticated WebSocket access when no relay token is configured by treating 'no token' as implicitly allowed, even though the startup log suggests otherwise. This can expose the voice relay, STT/TTS usage, history, and downstream OpenClaw interaction to any reachable client if the service is internet-accessible or mis-networked.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
### Security
- **Tailscale APT install**: Replaced `curl | sh` with official APT repository for Tailscale installation
- **Context sanitization**: User context is stripped to natural-language characters only (letters, numbers, common punctuation). IP addresses and domains are removed. Capped at 1000 characters.
- **Provider keys in config.json**: API keys stored in `config.json` (chmod 600) instead of systemd environment variables
### Features
- **Sanitized context returned to client**: All context endpoints (PUT, POST, WebSocket) return the sanitized text so the app can show users exactly what is stored
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
### Security
- **Tailscale APT install**: Replaced `curl | sh` with official APT repository for Tailscale installation
- **Context sanitization**: User context is stripped to natural-language characters only (letters, numbers, common punctuation). IP addresses and domains are removed. Capped at 1000 characters.
- **Provider keys in config.json**: API keys stored in `config.json` (chmod 600) instead of systemd environment variables
### Features
- **Sanitized context returned to client**: All context endpoints (PUT, POST, WebSocket) return the sanitized text so the app can show users exactly what is stored
The README instructs users to run a repository-controlled setup script with sudo bash, which grants full root privileges to whatever code is in the cloned repo. Even if the project is legitimate, this creates a real supply-chain and privilege-escalation risk because a compromised repo, malicious commit, or unsafe setup logic would execute as root on the host.
git clone https://github.com/fbn3799/clack-skill.git ~/.openclaw/skills/clack
sudo bash ~/.openclaw/skills/clack/scripts/setup.sh
This clones the repo and runs the interactive setup.
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.
## Configuration
Service configuration is via environment variables (set in the systemd service file). Provider API keys are stored separately in `config.json` (created by the setup script).
| Variable | Default | Description |
|----------|---------|-------------|
No suspicious patterns detected.