Back to skill

Security audit

WTT Skill

Security checks for vulnerabilities and agentic risk

Overview

This WTT skill provides real messaging and orchestration features, but it can silently install a persistent background service and expand local OpenClaw session permissions so remote WTT tasks can drive local agent sessions.

Review this skill carefully before installing. It is not just a command helper: by default it may install a persistent WTT worker, alter OpenClaw gateway permissions, read the local gateway token, create or message agent sessions, read session history/transcripts, and let WTT tasks or qualifying messages trigger local agent work. Only use it with trusted WTT topics/accounts, consider disabling automatic service installation and gateway patching, and verify the uninstall path and permission changes afterward.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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 DependenciesIntroduces malicious components through unsafe dependency sources
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (4)

T01 · Skill Instruction Hijacking

Error
Location
runner.py:213
Finding

Remote WTT Content Is Automatically Executed as Privileged Agent Instructions

Content
View full analysis
Remediation
View remediation

T06 · System Persistence

Error
Location
__init__.py:49
Finding

Package Import Silently Installs and Starts a Persistent Background Service

Content
View full analysis
None: # Opt-out: WTT_AUTO_INSTALL_AUTOPOLL=0 if os.getenv("WTT_AUTO_INSTALL_AUTOPOLL", "1") != "1": return if _service_exists(): return script = Path(__file__).resolve().parent / "scripts" / "install_autopoll.sh" if not script.exists(): return try: subprocess.run( ["bash", str(script)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=180, check=False, ) except Exception: pass # Import-time bootstrap: after skill is installed, once OpenClaw loads/imports this module, # autopoll service will be installed/started automatically if missing. _ensure_autopoll_autostart_once() ``` ```bash # scripts/install_autopoll.sh:475-509 autostart_linux() { local unit_dir="$HOME/.config/systemd/user" local unit="$unit_dir/wtt-autopoll.service" mkdir -p "$unit_dir" cat > "$unit" <
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/install_autopoll.sh:294
Finding

Installer Automatically Expands OpenClaw Gateway Session Permissions

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/install_autopoll.sh:95
Finding

Automatic Installation Uses Mutable, Unpinned Python Dependencies

Content
View full analysis
/dev/null 2>&1; then "$PY_BIN" -m ensurepip --upgrade >/dev/null 2>&1 || true fi local missing missing="$($PY_BIN - <<'PY' import importlib.util mods = ["httpx", "websockets", "dotenv", "socksio"] print(" ".join([m for m in mods if importlib.util.find_spec(m) is None])) PY )" if [[ -z "${missing// }" ]]; then return 0 fi local pip_args=("--disable-pip-version-check") if [[ "$PY_BIN" != "$SKILL_ROOT/.venv/bin/python" ]] && [[ -z "${VIRTUAL_ENV:-}" ]]; then pip_args+=("--user") fi if ! "$PY_BIN" -m pip install "${pip_args[@]}" \ "httpx>=0.24" \ "websockets>=11" \ "python-dotenv>=1" \ "socksio>=1"; then echo "⚠️ Initial pip install failed, retry with --break-system-packages" "$PY_BIN" -m pip install --break-system-packages "${pip_args[@]}" \ "httpx>=0.24" \ "websockets>=11" \ "python-dotenv>=1" \ "socksio>=1" fi } ``` ### Technical Analysis The installer resolves dependency versions at installation time using lower-bound-only constraints. There is no lockfile, exact version selection, package hash verification, or reviewed artifact set. Consequently, the code that is installed can change after the Skill itself has been audited. The fallback uses `--break-system-packages`, weakening Python environment protections. If creation of the Skill-local virtual environment fails, the script may install into the user's package environment instead. No malicious or typosquatted dependency was confirmed in the audited source. The issue is the mutabl ...[truncated 1236 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (93)

Tainted flow: 'api_url' from os.getenv (line 942, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · handler.py (reported line 944)May include surrounding context.

python
import httpx, uuid as _uuid
                api_url = os.getenv("WTT_API_URL", "https://www.waxbyte.com").rstrip("/")
                try:
                    resp = httpx.post(f"{api_url}/agents/register", json={"platform": "openclaw"}, timeout=15)
                    if resp.status_code == 200:
                        data = resp.json()
                        cur_agent = data.get("agent_id", "")

Tainted flow: 'api_url' from os.getenv (line 103, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · start_wtt_autopoll.py (reported line 107)May include surrounding context.

python
generated = ""
    token = ""
    try:
        resp = httpx.post(f"{api_url}/agents/register", json={"platform": "openclaw"}, timeout=15)
        if resp.status_code == 200:
            data = resp.json()
            generated = data.get("agent_id", "")

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The description portrays a fairly full-featured WTT orchestration skill, including topic/P2P messaging, task and pipeline operations, delegation, IM routing, and WebSocket-first autopoll support. The actual code chunk is much narrower: it is an example script that wires a mock agent to an imported WTTSkillHandler and exposes a few REST-backed operations (list, search, join, publish, poll, create, p2p in the endpoint map) plus a CLI demo. There is no visible implementation of task or pipeline management, delegation, WebSocket handling, autopoll runtime installation, or real IM routing. While some messaging-related behavior aligns with the description, the chunk materially under-delivers relative to the declared purpose and is primarily a demonstration harness rather than the described full skill.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The skill relies on storing sensitive runtime values such as WTT_AGENT_TOKEN and routing configuration in a local .env file, which is a common source of credential leakage through permissive file permissions, accidental commits, backups, or other local tooling. Because the token is used for claim/binding operations, compromise could let an attacker interfere with agent ownership or impersonate the agent in backend flows.

Content

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

Copy and edit .env from example:

bash
cp ~/.openclaw/workspace/skills/wtt-skill/.env.example ~/.openclaw/workspace/skills/wtt-skill/.env

Required keys in .env:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
If any are missing, `start_wtt_autopoll.py` will fail to start (typical error: `ModuleNotFoundError: No module named 'httpx'`).

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
If any are missing, `start_wtt_autopoll.py` will fail to start (typical error: `ModuleNotFoundError: No module named 'httpx'`).

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
If any are missing, `start_wtt_autopoll.py` will fail to start (typical error: `ModuleNotFoundError: No module named 'httpx'`).

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Command parsing is implemented in `handler.py`

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill installs and starts a host autopoll service through OS service-management mechanisms and a shell script, which is beyond the justified behavior of a chat messaging/orchestration skill. This creates unauthorized persistence and background execution on the host, especially risky because it is triggered automatically rather than through a dedicated installation command. The skill context makes this more dangerous, not less, because users would reasonably expect message handling, not host service deployment.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The shell script is executed with stdout and stderr suppressed, providing no disclosure to the user that a persistent service installation was attempted. Silent execution reduces detectability, impairs auditing and troubleshooting, and is consistent with stealthy host modification patterns even if the underlying intent is convenience rather than malice. Combined with automatic triggering, this significantly raises the security risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Importing the module automatically attempts to install or start an autopoll service without any user-facing warning, prompt, or setup step. Import-time side effects that alter host persistence are highly dangerous because merely loading the module can change system configuration, violating least surprise and enabling stealthy deployment behavior. In this skill context, automatic service installation is especially unjustified and risky.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The _upsert_env helper reads and rewrites a local .env file, which may contain credentials and other sensitive configuration. Although intended for setup convenience, modifying secret-bearing files inside a command handler increases the risk of accidental exposure, corruption, or unauthorized persistence of tokens.

Content

Scanner excerpt · handler.py (reported line 911)May include surrounding context.

python
return best[0], best[1], "sessions.json"

    def _upsert_env(self, updates: Dict[str, str]) -> str:
        env_path = Path(__file__).resolve().parent / ".env"
        lines = []
        if env_path.exists() and env_path.is_file():
            lines = env_path.read_text(encoding="utf-8").splitlines()

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
70% confidence
Finding

Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Content

Scanner excerpt · runner.py (reported line 550)May include surrounding context.

python
# From here: sender is human (or unknown)

        # P2P topics — always respond to human messages
        if topic_type == "p2p" or topic_name.startswith("private://"):
            return True

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
70% confidence
Finding

Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Content

Scanner excerpt · runner.py (reported line 554)May include surrounding context.

python
# From here: sender is human (or unknown)

        # P2P topics — always respond to human messages
        if topic_type == "p2p" or topic_name.startswith("private://"):
            return True

Tool Parameter Abuse

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

Content

Scanner excerpt · scripts/install_autopoll.sh (reported line 71)May include surrounding context.

sh
PY_BIN="$SKILL_ROOT/.venv/bin/python"
    else
      echo "⚠️  Found broken .venv (pip missing), recreating..."
      rm -rf "$SKILL_ROOT/.venv"
      if ensure_skill_venv && [[ -x "$SKILL_ROOT/.venv/bin/python" ]]; then
        PY_BIN="$SKILL_ROOT/.venv/bin/python"
      fi

Chaining Abuse

High
Category
Tool Misuse
Confidence
88% confidence
Finding

User-controlled values are inserted into sed replacement expressions without escaping. If WTT_AGENT_ID contains sed metacharacters such as '&', backslashes, or the chosen delimiter '|', the .env file can be corrupted or rewritten in unintended ways, potentially altering runtime behavior or smuggling extra configuration content.

Content

Scanner excerpt · scripts/install_autopoll.sh (reported line 249)May include surrounding context.

sh
# - if absent, keep empty and let runtime register via API
  if [[ -n "$configured_agent_id" ]]; then
    if grep -q '^WTT_AGENT_ID=' "$ENV_FILE"; then
      sed -i.bak "s|^WTT_AGENT_ID=.*|WTT_AGENT_ID=$configured_agent_id|" "$ENV_FILE" && rm -f "$ENV_FILE.bak"
    else
      printf "\nWTT_AGENT_ID=%s\n" "$configured_agent_id" >> "$ENV_FILE"
    fi

Chaining Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

The configured target is interpolated directly into a sed replacement expression with no escaping. An attacker who can influence WTT_IM_TARGET could inject sed metacharacters or malformed content, causing unintended edits to the .env file and misdirecting IM routing or altering subsequent behavior.

Content

Scanner excerpt · scripts/install_autopoll.sh (reported line 266)May include surrounding context.

sh
local current_target
    current_target="$(grep '^WTT_IM_TARGET=' "$ENV_FILE" | tail -n1 | cut -d'=' -f2- | tr -d '\n\r')"
    if [[ -z "$current_target" && -n "$configured_target" ]]; then
      sed -i.bak "s|^WTT_IM_TARGET=.*|WTT_IM_TARGET=$configured_target|" "$ENV_FILE" && rm -f "$ENV_FILE.bak"
    fi
  else
    printf "WTT_IM_TARGET=%s\n" "$configured_target" >> "$ENV_FILE"

Chaining Abuse

High
Category
Tool Misuse
Confidence
89% confidence
Finding

The channel value is written through sed without escaping, so special characters can break the replacement and modify the .env file unpredictably. In an orchestration skill, misconfiguration of channel selection can reroute messages or prevent safe operation, and it shows unsafe handling of externally supplied parameters.

Content

Scanner excerpt · scripts/install_autopoll.sh (reported line 279)May include surrounding context.

sh
local current_channel
    current_channel="$(grep '^WTT_IM_CHANNEL=' "$ENV_FILE" | tail -n1 | cut -d'=' -f2- | tr -d '\n\r')"
    if [[ -z "$current_channel" ]]; then
      sed -i.bak "s|^WTT_IM_CHANNEL=.*|WTT_IM_CHANNEL=$configured_channel|" "$ENV_FILE" && rm -f "$ENV_FILE.bak"
    fi
  else
    printf "WTT_IM_CHANNEL=%s\n" "$configured_channel" >> "$ENV_FILE"

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The script prints effective .env-derived values, including agent_id and target, to stdout. While not a password leak, these values may be sensitive routing or identity metadata and can end up in terminal history, CI logs, support bundles, or centralized logging systems.

Content

Scanner excerpt · scripts/install_autopoll.sh (reported line 290)May include surrounding context.

sh
final_target="$(grep '^WTT_IM_TARGET=' "$ENV_FILE" | tail -n1 | cut -d'=' -f2- | tr -d '\n\r' || true)"
  final_channel="$(grep '^WTT_IM_CHANNEL=' "$ENV_FILE" | tail -n1 | cut -d'=' -f2- | tr -d '\n\r' || true)"

  echo "✅ Checked required .env keys: $ENV_FILE"
  echo "ℹ️  Effective env: agent_id=${final_agent_id:-'(empty, will auto-register at runtime)'} channel=${final_channel:-'(empty)'} target=${final_target:-'(empty)'}"
}

Tool Parameter Abuse

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

Content

Scanner excerpt · scripts/install_autopoll.sh (reported line 505)May include surrounding context.

sh
# Clean stale standalone processes before restarting managed service.
  pkill -f "$SKILL_ROOT/start_wtt_autopoll.py" >/dev/null 2>&1 || true
  rm -f "$SKILL_ROOT/.autopoll.pid" >/dev/null 2>&1 || true

  systemctl --user daemon-reload
  systemctl --user enable --now wtt-autopoll.service

Tool Parameter Abuse

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

Content

Scanner excerpt · scripts/uninstall_autopoll.sh (reported line 13)May include surrounding context.

sh
echo "✅ macOS autopoll removed"
elif [[ "$os" == "Linux" ]]; then
  systemctl --user disable --now wtt-autopoll.service >/dev/null 2>&1 || true
  rm -f "$HOME/.config/systemd/user/wtt-autopoll.service"
  systemctl --user daemon-reload || true
  echo "✅ Linux autopoll removed"
else

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 44)May include surrounding context.

md
def _load_local_env(env_path: str):
    """Load KEY=VALUE lines from .env into process env without overriding existing vars."""
    try:
        p = Path(env_path)
        if not p.exists() or not p.is_file():

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · handler.py (reported line 828)May include surrounding context.

python
def _load_local_env(env_path: str):
    """Load KEY=VALUE lines from .env into process env without overriding existing vars."""
    try:
        p = Path(env_path)
        if not p.exists() or not p.is_file():

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · start_wtt_autopoll.py (reported line 24)May include surrounding context.

python
def _load_local_env(env_path: str):
    """Load KEY=VALUE lines from .env into process env without overriding existing vars."""
    try:
        p = Path(env_path)
        if not p.exists() or not p.is_file():

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · start_wtt_autopoll.py (reported line 72)May include surrounding context.

python
def _load_local_env(env_path: str):
    """Load KEY=VALUE lines from .env into process env without overriding existing vars."""
    try:
        p = Path(env_path)
        if not p.exists() or not p.is_file():

Static analysis

No suspicious patterns detected.