Back to skill

Security audit

Openclaw Tokenapi Qiehuan Skills

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real model-switching tool, but it exposes API keys and security settings through an unauthenticated local WebUI with misleading credential-storage documentation.

Review before installing. Use only least-privileged test API keys, avoid running the WebUI while browsing untrusted sites, and do not use this package to manage OpenClaw security settings until the local API has authentication, strict CORS/origin checks, masked key responses, and corrected credential-storage behavior.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
backend/app/api/routes.py:139
Finding

Unauthenticated API Endpoint Discloses Decrypted Provider API Keys

Content
View full analysis

Vulnerability Details

File Location: backend/app/api/routes.py:139-155; supporting credential decryption in backend/secure_config.py:78-96 and permissive CORS in backend/app/main.py:23-29
Vulnerability Type: Missing authentication and sensitive-data exposure
Risk Level: Critical

Vulnerable Code

python
@router.get("/provider/{provider_id}")
async def get_provider_config(provider_id: str):
    """Get a single provider configuration from encrypted storage."""
    try:
        config = secure_config.get_provider(provider_id)
        if config is None:
            return {
                "providerId": provider_id,
                "baseUrl": "",
                "apiKey": "",
                "contextWindow": 64000,
                "maxTokens": 8000,
            }
        return {"providerId": provider_id, **config}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

The returned configuration is decrypted by the following code:

python
def get_provider(self, provider_id: str) -> Optional[Dict]:
    try:
        if provider_id not in self.config.get("providers", {}):
            return None
        provider = self.config["providers"][provider_id]
        decrypted_apikey = SecureConfig._cipher.decrypt(
            provider["apiKey"].encode()
        ).decode()
        return {
            "baseUrl": provider["baseUrl"],
            "apiKey": decrypted_apikey,
            "contextWindow": provider.get("contextWindow", 64000),
            "maxTokens": provider.get("maxTokens", 8000),
        }
    except Exception as e:
        print(f"[SecureConfig] Failed to get provider configuration: {e}")
        return None

The application also enables unrestricted cross-origin requests:

python
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Technical Analysis

The provider endpoint has no authent ...[truncated 1892 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove apiKey from all provider read responses.
  2. Return only masked metadata, such as hasApiKey: true or a suffix like ****abcd.
  3. Require re-entry of a key when the user wants to replace it.
  4. Add authentication to every API endpoint, using a high-entropy token generated at startup or an authenticated local session.
  5. Replace wildcard CORS with the exact trusted WebUI origin:
    python
    allow_origins=["http://127.0.0.1:9131"]
    
  6. Validate the Origin and Host headers and reject untrusted origins.
  7. Add CSRF protection for all state-changing endpoints.
  8. Keep the service bound exclusively to loopback and document that it must not be exposed through a proxy.
  9. Rotate all API keys that may have been exposed through this endpoint.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
backend/app/api/routes.py:240
Finding

Unauthenticated Endpoint Can Weaken OpenClaw Execution and Sandbox Policies

Content
View full analysis

Vulnerability Details

File Location: backend/app/api/routes.py:240-259; policy mutation in backend/app/core/config_manager.py:339-379
Vulnerability Type: Unauthorized security-policy modification and excessive privilege
Risk Level: High

Vulnerable Code

python
@router.get("/settings")
async def get_advanced_settings():
    """Get advanced settings."""
    try:
        settings = config_manager.get_advanced_settings()
        return settings
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.put("/settings")
async def update_advanced_settings(settings: AdvancedSettingsSchema):
    """Update advanced settings."""
    try:
        success = config_manager.update_advanced_settings(settings.model_dump())
        if not success:
            raise HTTPException(status_code=500, detail="Failed to save advanced settings")
        return {"success": True, "message": "Advanced settings saved"}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

The endpoint directly changes OpenClaw security controls:

python
def update_advanced_settings(self, settings: Dict) -> bool:
    """Update advanced settings."""
    try:
        tools = self.config.setdefault("tools", {})
        exec_conf = tools.setdefault("exec", {})

        allow_list = []
        if settings.get("allowExec"): allow_list.append("exec")
        if settings.get("allowBrowser"): allow_list.append("browser")
        if settings.get("allowWebSearch"): allow_list.append("web_search")
        if settings.get("allowWebFetch"): allow_list.append("web_fetch")
        tools["allow"] = allow_list

        deny_list = []
        if settings.get("denyElevated"): deny_list.append("exec:elevated")
        if settings.get("denyShell"): deny_list.append("exec:shell")
        tools["deny"] = deny_list

        exec_conf["host"] = settings.get("execHost", "gateway")
        ex
...[truncated 3126 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove advanced execution and sandbox policy management from this model-switching Skill.
  2. If this functionality is essential, place it in a separately privileged administrative component.
  3. Require strong authentication and an explicit local confirmation for every privilege-increasing change.
  4. Add CSRF and strict origin protections.
  5. Replace unrestricted strings with Pydantic enums containing only supported safe values.
  6. Reject changes that weaken the existing policy unless separately authorized.
  7. Default to:
    • Execution disabled
    • Shell and elevated execution denied
    • User confirmation always required
    • Sandbox enabled
  8. Record security-policy changes in an audit log that excludes credentials.
  9. Use a dedicated configuration writer that can modify only explicitly approved fields.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
backend/app/api/routes.py:69
Finding

Unauthenticated Gateway Process Control Uses Shell-Based Command Execution

Content
View full analysis

Vulnerability Details

File Location: backend/app/api/routes.py:69-92; command implementation in backend/app/core/gateway.py:12-90
Vulnerability Type: Missing authorization for process control and unsafe shell invocation
Risk Level: High

Vulnerable Code

python
@router.post("/restart-gateway", response_model=ControlResponse)
async def restart_gateway_cmd():
    """Restart the Gateway using the configured command."""
    try:
        success, message = gateway_controller.restart_with_command()
        return ControlResponse(success=success, message=message)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/gateway/control", response_model=ControlResponse)
async def control_gateway(request: GatewayControlRequest):
    """Control the Gateway service."""
    try:
        success, message = gateway_controller.control_gateway(request.action)
        return ControlResponse(success=success, message=message)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

The controller invokes commands through the system shell:

python
@staticmethod
def _execute_command(command: str) -> Tuple[bool, str]:
    """Execute a command and return its result."""
    try:
        result = subprocess.run(
            command,
            shell=True,
            capture_output=True,
            text=True,
            encoding='utf-8',
            timeout=30
        )
        return result.returncode == 0, result.stdout + result.stderr
    except subprocess.TimeoutExpired:
        return False, "Command execution timed out"
    except Exception as e:
        return False, str(e)
python
@staticmethod
def start_gateway() -> Tuple[bool, str]:
    """Start the OpenClaw Gateway."""
    openclaw_home = os.path.join(os.path.expanduser("~"), ".openclaw")
    gateway_cmd = os.path.join(openclaw_home, "gateway.cmd")

    try:
        startupinfo = subprocess.STARTUPINFO()
   
...[truncated 2702 chars]
Remediation
View remediation

Remediation Suggestions

  1. Require authentication and authorization for all Gateway-control endpoints.
  2. Require an explicit local user confirmation before stopping or restarting the Gateway.
  3. Apply strict origin checks and CSRF protection.
  4. Remove shell=True.
  5. Execute fixed commands with argument arrays and shell=False.
  6. Verify that gateway.cmd is the expected file and is owned by the current user or a trusted administrator.
  7. Reject command files or parent directories writable by untrusted principals.
  8. Rate-limit restart and stop operations to prevent repeated denial of service.
  9. Prefer a narrowly scoped Gateway management API over operating-system shell commands.

T09 · Insecure Skill Coding Practices

Error
Location
backend/app/core/config_manager.py:300
Finding

Provider API Keys Are Duplicated into Plaintext Configuration Files

Content
View full analysis

Vulnerability Details

File Location: backend/app/core/config_manager.py:300-313 and backend/app/core/config_manager.py:381-420
Vulnerability Type: Plaintext credential storage
Risk Level: High

Vulnerable Code

python
def update_provider_apikey(self, provider_id: str, api_key: str) -> bool:
    """Update a provider API key in openclaw.json and auth-profiles.json."""
    try:
        providers = self.config.get("models", {}).get("providers", {})
        if provider_id not in providers:
            return False

        providers[provider_id]["apiKey"] = api_key
        openclaw_saved = self._save_config()

        self.update_auth_profile(provider_id, api_key)

        return openclaw_saved
    except Exception as e:
        print(f"Failed to update API key: {e}")
        return False

The same secret is written as a plaintext token to another file:

python
def update_auth_profile(self, provider_id: str, api_key: str) -> bool:
    """Update auth-profiles.json."""
    try:
        auth_profiles_path = os.path.join(
            os.path.expanduser("~"),
            ".openclaw",
            "agents",
            "main",
            "agent",
            "auth-profiles.json",
        )

        if os.path.exists(auth_profiles_path):
            with open(auth_profiles_path, "r", encoding="utf-8") as f:
                auth_config = json.load(f)
        else:
            auth_config = {"profiles": {}}

        profile_id = f"{provider_id}:manual"
        if "profiles" not in auth_config:
            auth_config["profiles"] = {}

        auth_config["profiles"][profile_id] = {
            "type": "token",
            "provider": provider_id,
            "token": api_key,
        }

        os.makedirs(os.path.dirname(auth_profiles_path), exist_ok=True)
        with open(auth_profiles_path, "w", encoding="utf-8") as f:
            json.dump(auth_config, f, indent=2, ensure_ascii=False)

        print(f"[ConfigManager] Updated auth-profiles
...[truncated 2300 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not store API keys in openclaw.json.
  2. Maintain a single authoritative secret store.
  3. Prefer the operating system's credential manager, such as Windows Credential Manager or DPAPI.
  4. If auth-profiles.json is required by OpenClaw, restrict its ACL to the owning user and the exact OpenClaw process identity.
  5. Create files atomically with owner-only permissions and verify permissions after every write.
  6. Store only a credential reference or profile identifier in the general model configuration.
  7. Securely migrate and remove existing plaintext apiKey fields.
  8. Rotate credentials that were previously persisted in plaintext.
  9. Avoid copying secret files into logs, backups, support bundles, or synchronization directories.

other

Warning
Location
SKILL.md:53
Finding

Security Documentation Misrepresents API-Key Transmission and Storage

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:53-57
Vulnerability Type: Misleading security documentation
Risk Level: Medium

Vulnerable Documentation

markdown
## Security Design

- API keys are stored only in browser localStorage and are not uploaded to any server.
- The backend only reads and writes the portions of openclaw.json that do not contain API keys.
- API keys are also written to ~/.openclaw/agents/main/agent/auth-profiles.json for OpenClaw.

Technical Analysis

The implementation contradicts the first two claims:

  • /api/save and /api/provider/apikey submit API keys from the browser to the backend.
  • ConfigManager.update_provider_apikey() and update_provider_config() write keys into openclaw.json.
  • update_auth_profile() writes plaintext tokens into auth-profiles.json.
  • GET /api/provider/{provider_id} returns decrypted keys over HTTP.

The documentation therefore understates both network transmission and local persistence of credentials. Users cannot make an informed security decision when the documented data flow does not match the implementation.

Attack Path

  1. A user reviews the stated security design and concludes that the API key remains in browser-local storage.
  2. The user enters a high-value provider credential into the WebUI.
  3. The frontend sends the credential to the backend.
  4. The backend stores it in multiple files and makes it retrievable through an unauthenticated endpoint.
  5. The credential becomes exposed to the local-web and plaintext-storage attack paths described above.

Impact Assessment

The documentation does not independently execute an attack, but it materially increases exposure by encouraging users to provide credentials under incorrect assumptions. This may result in use of higher-privilege or production credentials than the user would otherwise provide.

Remediation
View remediation

Remediation Suggestions

  1. Update the documentation to accurately describe every credential flow and storage location.
  2. State that keys are sent to the localhost backend when configurations are saved.
  3. Disclose whether and where plaintext copies are required by OpenClaw.
  4. Document the localhost API threat model, including malicious websites and local processes.
  5. Recommend least-privileged, separately scoped provider keys.
  6. After correcting the implementation, revise the security claims to match the new behavior and add automated tests that enforce those claims.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (60)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

This is a true tool-parameter-abuse risk because _execute_command is a reusable wrapper that sends its command parameter directly into a shell. In an agent or service context, any future path from external input to this function would grant arbitrary command execution, making the abstraction itself dangerous.

Content

Scanner excerpt · backend/app/core/gateway.py (reported line 15)May include surrounding context.

python
def _execute_command(command: str) -> Tuple[bool, str]:
        """执行命令并返回结果"""
        try:
            result = subprocess.run(
                command,
                shell=True,
                capture_output=True,

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This duplicate finding refers to the same shell-mediated Popen call in start_gateway. In this skill context, a gateway-management component is expected to spawn processes, but hidden execution from a user-writable location still increases danger because it can mask malicious replacement of the launcher script.

Content

Scanner excerpt · backend/app/core/gateway.py (reported line 57)May include surrounding context.

python
startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
            subprocess.Popen(
                f'"{gateway_cmd}"',
                shell=True,
                startupinfo=startupinfo,

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This duplicate finding refers to the same shell-mediated Popen call in start_gateway. In this skill context, a gateway-management component is expected to spawn processes, but hidden execution from a user-writable location still increases danger because it can mask malicious replacement of the launcher script.

Content

Scanner excerpt · backend/app/core/gateway.py (reported line 57)May include surrounding context.

python
startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
            subprocess.Popen(
                f'"{gateway_cmd}"',
                shell=True,
                startupinfo=startupinfo,

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This duplicate finding points to the same restart batch-script execution. The context makes it somewhat more dangerous because the code intentionally spawns external restart logic, which broadens the trusted computing base to an easily modified script file.

Content

Scanner excerpt · backend/app/core/gateway.py (reported line 87)May include surrounding context.

python
script_path = os.path.join(project_root, "tools", "restart_gateway.bat")

        try:
            subprocess.Popen([script_path], shell=True)
            GatewayController._log(f"Restart script executed: {script_path}")
            return True, "已打开 PowerShell 窗口执行重启命令"
        except Exception as e:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This duplicate finding points to the same restart batch-script execution. The context makes it somewhat more dangerous because the code intentionally spawns external restart logic, which broadens the trusted computing base to an easily modified script file.

Content

Scanner excerpt · backend/app/core/gateway.py (reported line 87)May include surrounding context.

python
script_path = os.path.join(project_root, "tools", "restart_gateway.bat")

        try:
            subprocess.Popen([script_path], shell=True)
            GatewayController._log(f"Restart script executed: {script_path}")
            return True, "已打开 PowerShell 窗口执行重启命令"
        except Exception as e:

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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/switch_model.py (reported line 90)May include surrounding context.

python
print("正在重启 OpenClaw Gateway...")
    try:
        # 尝试用 taskkill
        subprocess.run("taskkill /F /IM openclaw.exe", shell=True, capture_output=True)
        time.sleep(1)
    except Exception:
        pass

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This duplicate finding points to the same risky behavior: starting gateway.cmd through the shell from ~/.openclaw. In the skill context, a helper script that restarts infrastructure makes this more dangerous because users may run it routinely, giving a planted batch file a reliable execution path.

Content

Scanner excerpt · scripts/switch_model.py (reported line 98)May include surrounding context.

python
# 启动 gateway
    gateway_cmd = os.path.join(os.path.expanduser("~"), ".openclaw", "gateway.cmd")
    if os.path.exists(gateway_cmd):
        subprocess.Popen(f'"{gateway_cmd}"', shell=True, creationflags=0x08000000)
        print("✓ Gateway 重启完成")
    else:
        print(f"! Gateway 启动脚本不存在: {gateway_cmd}")

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This duplicate finding points to the same risky behavior: starting gateway.cmd through the shell from ~/.openclaw. In the skill context, a helper script that restarts infrastructure makes this more dangerous because users may run it routinely, giving a planted batch file a reliable execution path.

Content

Scanner excerpt · scripts/switch_model.py (reported line 98)May include surrounding context.

python
# 启动 gateway
    gateway_cmd = os.path.join(os.path.expanduser("~"), ".openclaw", "gateway.cmd")
    if os.path.exists(gateway_cmd):
        subprocess.Popen(f'"{gateway_cmd}"', shell=True, creationflags=0x08000000)
        print("✓ Gateway 重启完成")
    else:
        print(f"! Gateway 启动脚本不存在: {gateway_cmd}")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The feature list highlights automatic API key remembrance in browser localStorage, but the skill does not clearly warn at the point of use that credentials are also persisted locally and may remain accessible to the same browser profile or local user context. Storing secrets in localStorage and local auth files increases exposure to local compromise, browser profile theft, or other scripts running in the same origin if the web UI is ever exposed.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases include broad everyday language such as requests to switch models or open model management, which can cause accidental invocation during normal conversation. Because this skill can launch a local service and modify runtime configuration, overbroad activation materially increases the chance of unintended sensitive actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill states that saying a simple phrase will directly modify openclaw.json and restart service components, but it does not prominently warn users about these side effects or require explicit consent. Hidden or under-disclosed configuration changes and restarts can disrupt service availability, alter routing to different providers, and create opportunities for misuse through accidental activation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation makes a reassuring claim that API keys are only stored locally and not uploaded to any server, yet the same section states that keys are written into a local auth file used by OpenClaw and the backend/API design clearly participates in configuration management. Misleading security claims can cause users to expose secrets under false assumptions, especially when a local web backend is involved and the trust boundary is not clearly described.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This JavaScript bundle contains extensive hard-coded Chinese UI strings such as provider labels, prompts, restart instructions, and import template content, with no indication of user locale selection or an explicit region-specific scope. That creates a natural-language locale policy issue because the skill appears to enforce a specific language experience without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
78% confidence
Finding

The restart and control endpoints perform service-management actions that can affect system availability, yet there is no visible warning, confirmation step, or explanatory comment disclosing this impact to users. Although the route names indicate control behavior, the file does not provide any explicit caution about restarting or stopping the gateway service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code exposes a delete operation that removes a model or provider, which is a destructive action, but the implementation only logs internally and provides no confirmation prompt, cautionary comment, or user-facing disclosure about the deletion. Under the code-file criteria, destructive or irreversible operations should have some visible warning unless clearly documented elsewhere, which is not present in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The file's natural-language content, including docstrings and user-visible print messages, is consistently in Chinese, which imposes a specific language/locale on user-facing interactions. There is no indication that the user can choose the language or that this locale restriction is intentionally documented as region-specific.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The docstring at L219 states '只切换模型(不保存到通讯录)' ('only switch model'), implying a limited/non-persistent action, but the implementation updates config state and persists it via _save_config() at L237. This is an active contradiction between the inline intent documentation and the code's behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code stores API keys in plaintext in both openclaw.json and auth-profiles.json under the user's home directory, with no visible permission hardening, encryption, or explicit user warning at the point of storage. If the local filesystem is exposed through backups, misconfigured permissions, shared accounts, or malware, credentials can be recovered and used to access external provider accounts.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
96% confidence
Finding

_execute_command invokes subprocess.run with shell=True on an arbitrary string parameter. Although current in-file callers pass fixed commands, this helper is generic and creates a command-injection sink if any present or future caller passes user-influenced input, allowing arbitrary OS command execution.

Content

Scanner excerpt · backend/app/core/gateway.py (reported line 15)May include surrounding context.

python
def _execute_command(command: str) -> Tuple[bool, str]:
        """执行命令并返回结果"""
        try:
            result = subprocess.run(
                command,
                shell=True,
                capture_output=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code force-kills the openclaw.exe process using taskkill /F, which is a destructive operation that can interrupt active work or leave state unsafely terminated. The file includes only a generic status log and no confirmation prompt or explicit disclosure that the action is forceful and potentially disruptive.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
88% confidence
Finding

start_gateway launches a command via subprocess.Popen with shell=True and a path derived from the user's home directory. If an attacker can place or replace ~/.openclaw/gateway.cmd, this code will execute that attacker-controlled script, and shell invocation adds unnecessary parsing risk.

Content

Scanner excerpt · backend/app/core/gateway.py (reported line 57)May include surrounding context.

python
startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
            subprocess.Popen(
                f'"{gateway_cmd}"',
                shell=True,
                startupinfo=startupinfo,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The function spawns gateway.cmd via subprocess.Popen with shell=True and hides the window, which is safety-relevant process execution. Although there is a generic log message, the code does not clearly disclose that it will launch a background shell command from the user's home directory.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
84% confidence
Finding

restart_with_command executes an external batch script with subprocess.Popen and shell=True. Even though the path is built from the project root, execution of a batch file through the shell can be abused if the project files are modified or if path resolution behaves unexpectedly on Windows.

Content

Scanner excerpt · backend/app/core/gateway.py (reported line 87)May include surrounding context.

python
script_path = os.path.join(project_root, "tools", "restart_gateway.bat")

        try:
            subprocess.Popen([script_path], shell=True)
            GatewayController._log(f"Restart script executed: {script_path}")
            return True, "已打开 PowerShell 窗口执行重启命令"
        except Exception as e:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code launches restart_gateway.bat through subprocess.Popen, which opens a new PowerShell window and executes a restart script. While a log is emitted, there is no prior confirmation or explicit warning that an external script and shell window will be launched.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.