T09 · Insecure Skill Coding Practices
- Location
scripts/blutrv-control.sh:21- Finding
Arbitrary shell execution through unsafe environment-file sourcing
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is mostly a Shelly thermostat manager, but it includes broader device-control and credential-handling behavior than its published scope clearly authorizes.
Review before installing. Use only with a trusted, tightly protected Shelly env file; avoid the raw cloud command; confirm every write that affects heating or relays; and prefer a version that removes firmware/calibration/relay controls or gates them behind explicit user approval and strict device allowlists.
scripts/blutrv-control.sh:21Arbitrary shell execution through unsafe environment-file sourcing
scripts/blutrv-control.sh:43Unvalidated RPC destination and raw JSON interpolation permit SSRF and request manipulation
scripts/shelly-cloud.sh:28Shelly cloud token may be exposed through an unvalidated server URI and URL-based authentication
scripts/blutrv-status.sh:15Predictable shared temporary cache permits symlink attacks, races, and telemetry disclosure
scripts/blutrv-control.sh:11Documented device identity verification is not enforced before thermostat writes
scripts/blutrv-control.sh:201Device-altering operations exceed the published operational scope and lack explicit safety authorization
Referenced artifact was not completely inspected
4. **Timeout-Handling** — `blutrv-status.sh` hat bereits integriertes Timeout + Fallback
The trigger list includes broad everyday phrases such as "heizung," "thermostat," and "raumtemperatur" without clear scoping or exclusion conditions. This can cause the skill to activate in loosely related conversations and potentially execute heating-control actions when the user did not explicitly intend to control physical devices.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
~/.openclaw/workspace/skills/shelly-blutrv-manager/scripts/blutrv-control.sh schlafzimmer 20
curl -s -X POST "http://192.168.0.101/rpc"
-H "Content-Type: application/json"
-d '{"method":"BluTrv.Call","params":{"id":200,"method":"TRV.SetTarget","params":{"id":0,"target_C":20}}}'
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- Store Shelly variables only in `~/.openclaw/skills/.shelly-blutrv-manager.env`.
- Never store cloud tokens in the repository.
- Never paste production tokens into chat logs or notes.
- Restrict the local env file with `chmod 600`.
## Safety Rules
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
Store only Shelly-related variables in that file and restrict permissions:
chmod 600 ~/.openclaw/skills/.shelly-blutrv-manager.env
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
Store only Shelly-related variables in that file and restrict permissions:
chmod 600 ~/.openclaw/skills/.shelly-blutrv-manager.env
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
Store only Shelly-related variables in that file and restrict permissions:
chmod 600 ~/.openclaw/skills/.shelly-blutrv-manager.env
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
echo "Setting BluTRV $trv_id to ${target_temp}°C via gateway $gateway_ip..."
local response
response=$(curl -s -m 10 -X POST "http://${gateway_ip}/rpc" \
-H "Content-Type: application/json" \
-d "{\"id\":1,\"method\":\"BluTrv.Call\",\"params\":{\"id\":${trv_id},\"method\":\"TRV.SetTarget\",\"params\":{\"id\":0,\"target_C\":${target_temp}}}}")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# Boost = TRV.SetBoost with boost_enable=true and boost_reason=manual
local response
response=$(curl -s -m 10 -X POST "http://${gateway_ip}/rpc" \
-H "Content-Type: application/json" \
-d "{\"id\":1,\"method\":\"BluTrv.Call\",\"params\":{\"id\":${trv_id},\"method\":\"TRV.SetBoost\",\"params\":{\"id\":0,\"boost_enable\":true,\"boost_reason\":\"manual\"}}}")
The override command accepts a duration parameter and tells the user the override will revert after that many seconds, but the implementation only sends a plain TRV.SetTarget request and never uses the duration value in the RPC call or schedules any later clearing action. This is an active contradiction between the inline documentation/user-facing text and the actual behavior.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
echo "Device info for BluTRV $trv_id via gateway $gateway_ip..."
curl -s -m 10 -X POST "http://${gateway_ip}/rpc" \
-H "Content-Type: application/json" \
-d "{\"id\":1,\"method\":\"BluTrv.GetRemoteDeviceInfo\",\"params\":{\"id\":${trv_id}}}" | jq '.result.device_info'
}
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
echo "Device info for BluTRV $trv_id via gateway $gateway_ip..."
curl -s -m 10 -X POST "http://${gateway_ip}/rpc" \
-H "Content-Type: application/json" \
-d "{\"id\":1,\"method\":\"BluTrv.GetRemoteDeviceInfo\",\"params\":{\"id\":${trv_id}}}" | jq '.result.device_info'
}
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
echo "Device info for BluTRV $trv_id via gateway $gateway_ip..."
curl -s -m 10 -X POST "http://${gateway_ip}/rpc" \
-H "Content-Type: application/json" \
-d "{\"id\":1,\"method\":\"BluTrv.GetRemoteDeviceInfo\",\"params\":{\"id\":${trv_id}}}" | jq '.result.device_info'
}
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
attempt=$((attempt + 1))
stderr_file=$(mktemp)
if response=$(
curl \
--silent \
--show-error \
--fail \
The usage text documents relay and thermostat commands that actively change device state, including toggling relays and setting target temperature, but it does not include any warning that these actions affect physical devices immediately. In the code path, these operations are executed directly via API calls without any confirmation prompt or cautionary disclosure to the user.
The raw command allows callers to reach arbitrary Shelly Cloud GET endpoints using the configured authentication token, bypassing the narrower, named operations the wrapper otherwise exposes. In an agent skill context, this expands the reachable API surface and can enable unintended reads or state-changing GET actions if the upstream API supports them, increasing the chance of misuse or prompt-driven overreach.
This shell code reads a per-user env file and exports matching variables into the process environment, which is access to potentially sensitive configuration data. There is no confirmation prompt, visible logging, or explanatory warning in the file indicating that local configuration and possible credentials will be loaded.
The function announces it is checking for firmware updates for a particular BluTRV ID, yet the request body calls BluTrv.CheckForUpdates without including the provided trv_id. That means the documentation and user-facing message describe per-device behavior that the code does not actually express.
The default target and sensor examples embed German room names such as 'schlafzimmer', 'wohnzimmer', and 'flur' as canonical aliases in code comments and defaults. This hard-codes a locale preference without offering a language choice or documenting that the skill is intentionally region- or language-specific.