T09 · Insecure Skill Coding Practices
- Location
check_status.py:74- Finding
Bearer credential can be transmitted to an unconstrained gateway with optional TLS verification bypass
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill has a legitimate device-status purpose, but it handles a bearer API key through a shared config file and can send it to an unvalidated gateway with TLS checks disabled.
Review this skill before installing. Use only a least-privilege, revocable API key, keep ~/.openclaw/.env owner-readable only, confirm AI_GATEWAY_HOST is the intended Closeli gateway, and do not set AI_GATEWAY_VERIFY_SSL=false outside isolated development. Be aware that the script fetches device-list metadata to display names.
check_status.py:74Bearer credential can be transmitted to an unconstrained gateway with optional TLS verification bypass
check_status.py:37Shared credential file is parsed beyond the configuration values required by the Skill
The skill is designed to read an API key from ~/.openclaw/.env, a shared persistent file readable by other skills under the same user according to the document itself. Storing sensitive credentials in a cross-skill shared location creates a credential exposure risk: any compromised or overly-permissive skill in the same environment could harvest the API key and use it against the gateway.
openclaw:
requires:
bins: ["python3"]
configPaths: ["~/.openclaw/.env"]
primaryEnv: "AI_GATEWAY_API_KEY"
---
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
`POST /api/device/status` is used to batch query the online/offline status of devices.
## ⚠️ Display Rules (MUST be strictly followed)
The script outputs structured data in JSON format, which is the expected behavior. The display rules below are formatting instructions for the agent: the agent MUST parse the JSON output from the script, convert it into a user-friendly format according to the following rules before displaying it, and MUST NOT display the raw JSON directly.
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
## ⚠️ Display Rules (MUST be strictly followed)
The script outputs structured data in JSON format, which is the expected behavior. The display rules below are formatting instructions for the agent: the agent MUST parse the JSON output from the script, convert it into a user-friendly format according to the following rules before displaying it, and MUST NOT display the raw JSON directly.
The script output includes the `_device_names` field (device_id → device_name mapping), which is used to display device names.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
批量查询设备在线/离线状态。自动调用 device/list 获取设备名称映射。
配置来源(统一规则):
- 持久化:~/.openclaw/.env (OpenClaw 客户端的"设置 API Key"会自动写入此文件)
- 临时覆盖:仅 API_KEY 支持命令行 --api-key,覆盖 .env 中的同名配置
- 不再读取任何 AI_GATEWAY_* 环境变量
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
批量查询设备在线/离线状态。自动调用 device/list 获取设备名称映射。
配置来源(统一规则):
- 持久化:~/.openclaw/.env (OpenClaw 客户端的"设置 API Key"会自动写入此文件)
- 临时覆盖:仅 API_KEY 支持命令行 --api-key,覆盖 .env 中的同名配置
- 不再读取任何 AI_GATEWAY_* 环境变量
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
批量查询设备在线/离线状态。自动调用 device/list 获取设备名称映射。
配置来源(统一规则):
- 持久化:~/.openclaw/.env (OpenClaw 客户端的"设置 API Key"会自动写入此文件)
- 临时覆盖:仅 API_KEY 支持命令行 --api-key,覆盖 .env 中的同名配置
- 不再读取任何 AI_GATEWAY_* 环境变量
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
批量查询设备在线/离线状态。自动调用 device/list 获取设备名称映射。
配置来源(统一规则):
- 持久化:~/.openclaw/.env (OpenClaw 客户端的"设置 API Key"会自动写入此文件)
- 临时覆盖:仅 API_KEY 支持命令行 --api-key,覆盖 .env 中的同名配置
- 不再读取任何 AI_GATEWAY_* 环境变量
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
批量查询设备在线/离线状态。自动调用 device/list 获取设备名称映射。
配置来源(统一规则):
- 持久化:~/.openclaw/.env (OpenClaw 客户端的"设置 API Key"会自动写入此文件)
- 临时覆盖:仅 API_KEY 支持命令行 --api-key,覆盖 .env 中的同名配置
- 不再读取任何 AI_GATEWAY_* 环境变量
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
批量查询设备在线/离线状态。自动调用 device/list 获取设备名称映射。
配置来源(统一规则):
- 持久化:~/.openclaw/.env (OpenClaw 客户端的"设置 API Key"会自动写入此文件)
- 临时覆盖:仅 API_KEY 支持命令行 --api-key,覆盖 .env 中的同名配置
- 不再读取任何 AI_GATEWAY_* 环境变量
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
批量查询设备在线/离线状态。自动调用 device/list 获取设备名称映射。
配置来源(统一规则):
- 持久化:~/.openclaw/.env (OpenClaw 客户端的"设置 API Key"会自动写入此文件)
- 临时覆盖:仅 API_KEY 支持命令行 --api-key,覆盖 .env 中的同名配置
- 不再读取任何 AI_GATEWAY_* 环境变量
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从 ~/.openclaw/.env 文件加载配置。
这是 OpenClaw 客户端写入的持久化真值源,由所有 skill 共享。
"""
env_path = Path.home() / ".openclaw" / ".env"
if not env_path.exists():
return {}
result = {}
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
从 ~/.openclaw/.env 文件加载配置。
这是 OpenClaw 客户端写入的持久化真值源,由所有 skill 共享。
"""
env_path = Path.home() / ".openclaw" / ".env"
if not env_path.exists():
return {}
result = {}
Allowing AI_GATEWAY_HOST to be read from a shared local .env file means the bearer token can be sent to an arbitrary host if that configuration is tampered with. In the context of a shared cross-skill configuration source, this creates a realistic credential redirection/exfiltration risk rather than simple local config use.
def get_api_host(env_vars):
"""
获取网关地址:~/.openclaw/.env 中的 AI_GATEWAY_HOST,未配置则用默认值。
"""
host = env_vars.get("AI_GATEWAY_HOST")
return host.rstrip("/") if host else DEFAULT_API_HOST
This logic accepts AI_GATEWAY_VERIFY_SSL=false from the shared .env file, enabling TLS certificate verification to be disabled. If combined with a hostile network or modified host setting, the bearer token and API responses become vulnerable to man-in-the-middle interception and tampering.
def get_verify_ssl(env_vars):
"""
判断是否启用 TLS 证书验证。默认启用。
仅当 ~/.openclaw/.env 中显式设置 AI_GATEWAY_VERIFY_SSL=false 时禁用(仅开发环境)。
"""
val = env_vars.get("AI_GATEWAY_VERIFY_SSL", "true").lower()
return val not in ("false", "0", "no")
The skill declares network access and reads a shared credential file, but it does not declare any explicit tool scope such as permissions or allowed-tools. In agent ecosystems, missing scope boundaries can let the runtime grant broader file-read or network capability than the skill actually needs, increasing the blast radius if the skill is misused or later modified.
The skill explicitly relies on a persistent shared configuration file as the single source of truth for gateway credentials and host settings. Session persistence itself is not always unsafe, but here it increases risk because sensitive values persist across runs and are shared among skills, enabling stale, poisoned, or unauthorized reuse of credentials and endpoint configuration.
### Configuration Source
The script reads `~/.openclaw/.env` as the single persistent configuration source. This file is shared by all skills and uses the format `KEY=VALUE` (one entry per line). OpenClaw clients write to this file when the user updates settings. The script does NOT read any `AI_GATEWAY_*` environment variables — env variables are intentionally ignored to avoid stale Gateway-process snapshots overriding the user's latest config.
## Security Notes
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
## Security Notes
- The shared credential file `~/.openclaw/.env` is readable by all skills under the same user. Ensure file permissions are restricted (e.g. `chmod 600 ~/.openclaw/.env`) and that only the OpenClaw service user has access. The IM clients write to this file under that user's home directory.
- TLS certificate verification is enabled by default. You MUST NOT disable it in production environments (disabling it introduces man-in-the-middle attack risks, and attackers may intercept API_KEY and device data)
- Before use, you MUST confirm that AI_GATEWAY_HOST points to a trusted domain
- You MUST use a least-privilege API_KEY to avoid reusing high-privilege credentials. This skill only requires device status query permission
The skill has an unsafe transport option: a shared configuration value can disable SSL verification, undermining the authenticity of the HTTPS connection. In this skill, which transmits a bearer API key and receives device status data, that materially increases the chance of credential theft and response manipulation.
def get_verify_ssl(env_vars):
"""
判断是否启用 TLS 证书验证。默认启用。
仅当 ~/.openclaw/.env 中显式设置 AI_GATEWAY_VERIFY_SSL=false 时禁用(仅开发环境)。
"""
val = env_vars.get("AI_GATEWAY_VERIFY_SSL", "true").lower()
return val not in ("false", "0", "no")
The script fetches the full device inventory via /api/device/list before performing a status query, which exceeds the narrowly described device-status scope. Even if used only to enrich output with names, this broadens data access and can reveal metadata for devices unrelated to the requested IDs if the credential has wider permissions.