Back to skill

Security audit

Rendered

Security checks across malware telemetry and agentic risk

Overview

This is a disclosed persistent ClawArena game watcher that stores a scoped token and runs local OpenClaw turns; the sensitive behavior matches the skill's stated purpose.

Install only if you want persistent autonomous ClawArena play on this machine. Use a dedicated OpenClaw agent via CLAWARENA_OPENCLAW_AGENT_ID if you do not want game turns using your main agent's tool policy, keep setup/recovery keys private, and expect local token/state files plus a background watcher until you stop it.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
timeout: float,
    ) -> subprocess.CompletedProcess[str]:
        """Run one model turn in an isolated process group."""
        return subprocess.run(  # noqa: S603
            cmd,
            capture_output=True,
            text=True,
Confidence
87% confidence
Finding
return subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=timeout, check=False, cwd=stable_subpr

subprocess module call

Medium
Category
Dangerous Code Execution
Content
thread_id = delivery.get("thread_id")
        if thread_id:
            cmd.extend(["--thread-id", str(thread_id)])
        proc = subprocess.run(  # noqa: S603
            cmd,
            capture_output=True,
            text=True,
Confidence
83% confidence
Finding
proc = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=30, check=False, cwd=stable_subprocess

subprocess module call

Medium
Category
Dangerous Code Execution
Content
self._append_delivery_args(cmd, delivery)

        try:
            proc = subprocess.run(  # noqa: S603
                cmd,
                capture_output=True,
                text=True,
Confidence
83% confidence
Finding
proc = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=120, check=False,

subprocess module call

Medium
Category
Dangerous Code Execution
Content
self._append_delivery_args(cmd, delivery)

        try:
            proc = subprocess.run(  # noqa: S603
                cmd,
                capture_output=True,
                text=True,
Confidence
83% confidence
Finding
proc = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=120, check=False,

subprocess module call

Medium
Category
Dangerous Code Execution
Content
self._build_reflection_message(wake, context),
                "--json",
            ]
            proc = subprocess.run(  # noqa: S603
                cmd,
                capture_output=True,
                text=True,
Confidence
85% confidence
Finding
proc = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=120, check=False,

Tainted flow: 'cmd' from os.environ.get (line 2586, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
timeout: float,
    ) -> subprocess.CompletedProcess[str]:
        """Run one model turn in an isolated process group."""
        return subprocess.run(  # noqa: S603
            cmd,
            capture_output=True,
            text=True,
Confidence
88% confidence
Finding
return subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=timeout, check=False, cwd=stable_subpr

Tainted flow: 'cmd' from os.environ.get (line 2586, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
thread_id = delivery.get("thread_id")
        if thread_id:
            cmd.extend(["--thread-id", str(thread_id)])
        proc = subprocess.run(  # noqa: S603
            cmd,
            capture_output=True,
            text=True,
Confidence
84% confidence
Finding
proc = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=30, check=False, cwd=stable_subprocess

Tainted flow: 'cmd' from os.environ.get (line 2586, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
self._append_delivery_args(cmd, delivery)

        try:
            proc = subprocess.run(  # noqa: S603
                cmd,
                capture_output=True,
                text=True,
Confidence
84% confidence
Finding
proc = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=120, check=False,

Tainted flow: 'cmd' from os.environ.get (line 2586, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
self._append_delivery_args(cmd, delivery)

        try:
            proc = subprocess.run(  # noqa: S603
                cmd,
                capture_output=True,
                text=True,
Confidence
84% confidence
Finding
proc = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=120, check=False,

Tainted flow: 'cmd' from os.environ.get (line 2586, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
self._build_reflection_message(wake, context),
                "--json",
            ]
            proc = subprocess.run(  # noqa: S603
                cmd,
                capture_output=True,
                text=True,
Confidence
86% confidence
Finding
proc = subprocess.run( # noqa: S603 cmd, capture_output=True, text=True, timeout=120, check=False,

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill declares no permissions while explicitly directing use of shell commands, persistent file writes, network access, environment variables, and background process management. This under-declaration hides the true attack surface from users and reviewers, increasing the risk of consent bypass and unsafe installation of a stateful networked skill.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description minimizes the skill as a token-storing watcher, but the document reveals substantially broader behavior: agent provisioning/recovery, telemetry, outbound chat delivery, maintenance notices, persistent state management, and server-driven reflection updates. This mismatch is dangerous because it obscures sensitive behaviors involving credentials, messaging, and autonomous remote-triggered actions on the user's local OpenClaw agent.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The file says setup 'creates no agent' while later sections describe provisioning a new Arena Agent in some modes. Contradictory security-relevant documentation can cause users or automation to authorize actions under false assumptions, particularly around account creation, token issuance, and persistent background services.

Description-Behavior Mismatch

Medium
Confidence
80% confidence
Finding
The manifest says the skill is a local turn watcher, but the code also performs post-match self-learning and writes updated strategy prompts back to the remote service. That mismatch expands the data-processing scope beyond what a user would reasonably expect, increasing privacy and trust risk.

Description-Behavior Mismatch

Low
Confidence
78% confidence
Finding
The code sends maintenance and update notices through OpenClaw delivery channels, but that behavior is not clearly disclosed by the manifest. Hidden messaging behavior is risky in an autonomous background skill because it can surprise users and create consent and abuse concerns.

Context-Inappropriate Capability

Medium
Confidence
82% confidence
Finding
This watcher can generate user-facing instructions encouraging a skill update command, which is beyond the narrow scope of turn watching. In a background agent that already stores a scoped token and has delivery routes, prompting maintenance actions materially broadens what the skill can influence users to do.

Session Persistence

Medium
Category
Rogue Agent
Content
- The watcher reports its installed skill version in heartbeat telemetry and can send a one-time update notice when the server requires a newer `test-ai-clawarena` skill.
- Use one direct `python3 /absolute/path/setup_local_watcher.py ...` invocation only. Do not wrap it in `bash -lc`, `sh`, heredocs, or `python -c`.
- Treat `setup_local_watcher.py` as a deterministic local setup script that provisions or reuses one agent, atomically manages credentials in its arena-scoped state directory, verifies the same local OpenClaw execution path used by gameplay, waits for server watcher readiness, and starts one local watcher process.
- Do not ask the user to create an OpenClaw agent, copy credentials, or edit
  tool policies. Gameplay runs on their existing agent with its own model and
  auth, which is what makes OAuth-authenticated OpenClaw work at all — those
  credentials cannot be copied into a second agent. A user who wants a separate
Confidence
83% confidence
Finding
create an OpenClaw agent, copy credentials, or edit tool policies. Gameplay runs on their existing agent with its own model and auth, which is what makes OAuth-authenticated OpenClaw work at all —

VirusTotal

65/65 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.