Back to skill

Security audit

agos claw chat

Security checks for vulnerabilities and agentic risk

Overview

This connector does what it advertises, but it creates a persistent bridge from a remote service to local command execution with weak token storage and limited disclosure.

Review this carefully before installing. Only run it in a dedicated low-privilege environment, use an API base you trust, avoid setting --agent-cmd unless you fully control the command, assume remote AITalk requests and local responses are shared with the service, and protect or rotate the saved connector token.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

other

Warning
Location
connector.py:287
Finding

Local Hostname Disclosed to the Remote Connector Service

Content
View full analysis

Vulnerability Details

File Location: connector.py:287-288; transmitted by connector.py:89-100
Vulnerability Type: Environment reconnaissance and unnecessary information disclosure
Risk Level: Medium

Vulnerable Code

python
def resolve_default_connector_id() -> str:
    hostname = socket.gethostname().split(".")[0]
    return f"agos-{hostname}-{uuid.uuid4().hex[:6]}"

The resulting identifier is transmitted during registration:

python
def register_with_code(self, match_code: str) -> ConnectorSession:
    resp = self.http.post(
        self._url("/api/v2/openclaw/connectors/register-with-code"),
        json={
            "match_code": match_code,
            "connector_id": self.connector_id,
            "client_version": VERSION,
            "capabilities": {"mode": "polling", "runtime": "python"},
        },
        timeout=self.timeout_sec,
    )

Technical Analysis

The default connector identifier incorporates the local machine hostname. That identifier is subsequently sent to the configured remote API during connector registration.

A unique connector identifier is legitimate for the declared functionality, but including the hostname is not necessary: an opaque UUID would provide sufficient uniqueness. Hostnames can reveal usernames, employee names, machine roles, deployment stages, internal asset conventions, or other infrastructure details.

The code only retrieves the short hostname. The reviewed implementation does not explicitly collect an IP address or full FQDN.

Attack Path

  1. A user starts the connector without supplying --connector-id or AITALK_CONNECTOR_ID.
  2. resolve_default_connector_id() reads the local hostname.
  3. The hostname is embedded in the generated connector identifier.
  4. Registration sends that identifier to the configured api_base.
  5. The remote service can store and correlate the hostname-derived identifier wit ...[truncated 383 chars]
Remediation
View remediation

Remediation Suggestions

  • Generate an opaque identifier without incorporating host information:

    python
    def resolve_default_connector_id() -> str:
        return f"agos-{uuid.uuid4().hex}"
    
  • Persist the random identifier locally if stable connector identity is required.

  • Make hostname disclosure an explicit, documented opt-in rather than a default.

  • Clearly disclose all device metadata transmitted during registration.

  • Validate and restrict api_base where possible so identifiers are not accidentally sent to an unintended endpoint.

T09 · Insecure Skill Coding Practices

Error
Location
connector.py:73
Finding

Bearer Session Token Stored Without Enforced Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: connector.py:73-83; default storage location configured at connector.py:297-300
Vulnerability Type: Plaintext sensitive-token storage with ambient filesystem permissions
Risk Level: High

Vulnerable Code

python
def _save_session(self, session: ConnectorSession) -> None:
    self.state_file.parent.mkdir(parents=True, exist_ok=True)
    payload = {
        "session_token": session.session_token,
        "provider_id": session.provider_id,
        "connector_session_id": session.connector_session_id,
        "heartbeat_interval_sec": session.heartbeat_interval_sec,
        "expires_at": session.expires_at.isoformat(),
        "updated_at": datetime.now(timezone.utc).isoformat(),
    }
    self.state_file.write_text(json.dumps(payload, indent=2), "utf-8")

The default path is:

python
parser.add_argument(
    "--state-file",
    default=os.getenv(
        "AITALK_STATE_FILE",
        str(Path.home() / ".aitalk" / "openclaw_connector_state.json"),
    ),
)

Technical Analysis

The connector saves its reusable bearer session token as plaintext using Path.write_text(). File permissions are determined by the process umask or by the permissions of an existing file. The implementation does not:

  • Create the token file explicitly with mode 0600.
  • Restrict the state directory to mode 0700.
  • Validate file ownership or permissions before loading it.
  • Protect against an attacker-controlled symbolic link at a configurable state path.
  • Use an operating-system credential store.

Because authenticated requests use the token directly in the Authorization: Bearer header, possession of the stored value may be sufficient to impersonate the connector until expiry or revocation.

Attack Path

  1. The victim registers the connector and receives a session token.
  2. _save_session() writes the token to the state file usi ...[truncated 932 chars]
Remediation
View remediation

Remediation Suggestions

  • Create the state directory with mode 0700.
  • Create or replace the state file atomically with mode 0600.
  • Verify that the path is owned by the current user, is a regular file, and is not a symbolic link before reading it.
  • Use a temporary file in the same protected directory, flush and synchronize it, then atomically replace the destination.
  • Prefer an operating-system credential manager for storing bearer tokens.
  • Rotate and revoke tokens after suspected exposure.
  • Minimize session lifetime and scope on the server.
  • Reject state files that are group- or world-readable.

Example hardening logic should use low-level file creation flags such as O_CREAT, O_EXCL, O_WRONLY, and, where supported, O_NOFOLLOW, with mode 0600.

T09 · Insecure Skill Coding Practices

Warning
Location
connector.py:193
Finding

Configurable Agent Command Executed Through a Shell

Content
View full analysis

Vulnerability Details

File Location: connector.py:193-207
Vulnerability Type: Shell command injection through unsafe configuration
Risk Level: Medium

Vulnerable Code

python
def _run_local_agent(self, message: str, request_payload: Dict[str, Any]) -> str:
    if not self.agent_cmd:
        return f"[AITalk Connector] {message}"

    env = os.environ.copy()
    env["OPENCLAW_MESSAGE"] = message
    env["OPENCLAW_PAYLOAD"] = json.dumps(request_payload)
    proc = subprocess.run(
        self.agent_cmd,
        shell=True,
        env=env,
        capture_output=True,
        text=True,
        timeout=90,
    )
    if proc.returncode != 0:
        stderr = (proc.stderr or "").strip()
        raise RuntimeError(stderr or f"agent command failed with code {proc.returncode}")

Technical Analysis

self.agent_cmd originates from the --agent-cmd argument or AITALK_AGENT_CMD environment variable and is executed with shell=True. Consequently, shell metacharacters, substitutions, redirections, pipelines, and compound commands are interpreted rather than treated as literal program arguments.

The remotely supplied message and payload are inserted into environment variables, not directly concatenated into the command. Therefore, the reviewed code does not establish direct remote shell injection from OPENCLAW_MESSAGE alone. Exploitation requires influence over connector configuration, its launch environment, or an agent command that subsequently interprets the attacker-controlled environment variables unsafely.

Shell use nevertheless expands the effect of configuration tampering from selecting a program to arbitrary command execution.

Attack Path

  1. An attacker gains the ability to modify AITALK_AGENT_CMD, startup configuration, a wrapper script, or connector command-line arguments.
  2. The attacker supplies a value containing shell syntax, such as a compound command ...[truncated 737 chars]
Remediation
View remediation

Remediation Suggestions

  • Avoid invoking a shell and execute an explicit argument vector:

    python
    import shlex
    
    argv = shlex.split(self.agent_cmd)
    proc = subprocess.run(
        argv,
        shell=False,
        env=env,
        capture_output=True,
        text=True,
        timeout=90,
        check=False,
    )
    
  • Prefer accepting the executable and arguments as a structured list rather than parsing one command string.

  • Validate the executable against an administrator-controlled allowlist when feasible.

  • Resolve the executable to an expected absolute path.

  • Run the local agent under a dedicated, minimally privileged account or sandbox.

  • Supply a reduced environment instead of copying all process environment variables.

  • Document that OPENCLAW_MESSAGE and OPENCLAW_PAYLOAD contain untrusted remote content.

  • Require local agent implementations to avoid passing those values to shells, template evaluators, or interpreters without strict validation.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Dependency Uses an Unbounded Version Range Without Integrity Hashes

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1; installation documented at README.md:5-10
Vulnerability Type: Non-reproducible dependency resolution and insufficient supply-chain integrity controls
Risk Level: Medium

Vulnerable Code

text
requests>=2.31.0

The documented installation procedure is:

bash
cd aitalk-connector-skill
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Technical Analysis

The dependency specification accepts version 2.31.0 and every future compatible or incompatible release selected by the package resolver. It does not pin a reviewed version, lock transitive dependencies, or require artifact hashes.

The package name requests is legitimate, and the reviewed project does not configure a suspicious package repository or include an evident typosquatted dependency. The risk arises from trusting future unreviewed releases and mutable resolution results rather than from a currently identified malicious package.

Attack Path

  1. A user follows the documented installation process at a later date.
  2. Package resolution selects dependency versions that were not part of this audit.
  3. A future package or transitive dependency is compromised, malicious, or unexpectedly incompatible.
  4. Pip downloads and installs the artifact without checking it against project-maintained hashes.
  5. Malicious installation or runtime code executes with the privileges of the user performing installation or running the connector.

Impact Assessment

A compromised dependency could execute code during installation or connector runtime, access files and environment variables available to the user, intercept match codes and bearer tokens, alter HTTPS requests, or manipulate connector results. The ultimate scope is limited by the privileges of the installation and runtime account, but users commonly install dependencies under account ...[truncated 20 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin direct and transitive dependencies to reviewed versions.

  • Generate a lock file appropriate for the supported Python tooling.

  • Record cryptographic hashes for all accepted distributions.

  • Install with hash enforcement, for example:

    bash
    pip install --require-hashes -r requirements.txt
    
  • Use a controlled package index or internal artifact mirror where appropriate.

  • Enable automated dependency vulnerability monitoring and review upgrades before release.

  • Regenerate the lock file and hashes through a documented, trusted release process.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (10)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
91% confidence
Finding

Copying the full parent environment into a child process exposes all existing environment secrets—API keys, cloud credentials, tokens, proxy settings—to the invoked agent command. In this connector, that child process is triggered by remote-sourced work, so any compromised or untrusted agent binary can harvest and exfiltrate sensitive credentials from the host environment.

Content

Scanner excerpt · connector.py (reported line 197)May include surrounding context.

python
if not self.agent_cmd:
            return f"[AITalk Connector] {message}"

        env = os.environ.copy()
        env["OPENCLAW_MESSAGE"] = message
        env["OPENCLAW_PAYLOAD"] = json.dumps(request_payload)
        proc = subprocess.run(

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

The tool invocation accepts a broad parameter, self.agent_cmd, and executes it through the shell, which is classic tool-parameter abuse. In context, the connector claims remote requests in a loop and feeds them to this execution path, so misconfiguration or abuse of the configured command can turn the connector into a remote-triggered local execution mechanism.

Content

Scanner excerpt · connector.py (reported line 200)May include surrounding context.

python
env = os.environ.copy()
        env["OPENCLAW_MESSAGE"] = message
        env["OPENCLAW_PAYLOAD"] = json.dumps(request_payload)
        proc = subprocess.run(
            self.agent_cmd,
            shell=True,
            env=env,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This is a markdown file, so SQP-2 applies to omissions in user-facing warnings. The notes say the connector registers with a remote endpoint, keeps a heartbeat, and long-polls for work requests, but the README does not warn users that running the skill will initiate persistent network activity and exchange system or session data with an external service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The session token is persisted in plaintext to a user-writable state file, creating a reusable secret at rest that can be stolen by other local users, malware, backups, or accidental disclosure. Because the token authorizes heartbeat, polling, and completion calls, compromise of the file can let an attacker impersonate the connector session.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The connector sends output_text, token usage, and error details back to the remote service in complete, and elsewhere long-polls for work from the API. Although network communication is part of the connector's function, the code does not clearly disclose to the user that local prompts/payloads and generated responses will be sent to the configured API endpoint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The issue is not merely missing warning text; the code exposes a dangerous capability by allowing shell command execution from configuration without guardrails. In a connector that continuously consumes remote requests, that creates a persistent execution surface where operators may unknowingly run unsafe commands that process attacker-controlled input.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

The connector executes a configured command via subprocess.run(..., shell=True), which invokes a shell interpreter and greatly expands the attack surface. In this skill’s context, the command is used to process untrusted remote request data passed through environment variables, so any unsafe command construction or downstream shell expansion can lead to arbitrary code execution on the host.

Content

Scanner excerpt · connector.py (reported line 200)May include surrounding context.

python
env = os.environ.copy()
        env["OPENCLAW_MESSAGE"] = message
        env["OPENCLAW_PAYLOAD"] = json.dumps(request_payload)
        proc = subprocess.run(
            self.agent_cmd,
            shell=True,
            env=env,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This connector is not merely forwarding requests; it is capable of launching an arbitrary local command supplied by configuration, which gives remote-triggered tasks access to local execution capability. That is dangerous because the long-polling server controls when execution occurs and what data is supplied to the local process, making the connector a bridge from remote input to privileged local actions.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified as requests>=2.31.0, which allows installation of any future version and does not guarantee a reproducible, reviewed dependency set. This weakens supply-chain assurance because different environments may resolve to different releases, including newly introduced vulnerable or breaking versions.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

Because requests is not pinned, it is impossible to verify from this manifest which exact release will be installed, and the package has multiple historical advisories. This creates supply-chain uncertainty: an environment could resolve to an affected version or an unexpected newer release, making risk assessment and patch validation unreliable.

Content

No source excerpt is available for this finding.