Back to skill

Security audit

Devialet Speaker Control

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches speaker control, but it also includes under-disclosed Spotify account automation and insecure token handling that users should review before installing.

Install only if you are comfortable granting Spotify playback-control access and letting the skill automate your local Spotify desktop session. Keep Devialet control limited to a trusted LAN, review or remove spotify.sh if you do not need OAuth-based Spotify control, and fix token permissions plus volume input validation before relying on it in automation.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/devialet.sh:131
Finding
Command Execution Through Unsafe Bash Arithmetic Evaluation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/devialet.sh:131-134` **Vulnerability Type**: Shell arithmetic injection **Risk Level**: High ### Vulnerable Code ```bash if [[ "$ARG" -lt 0 || "$ARG" -gt 100 ]]; then echo "Error: Volume must be 0-100" exit 1 fi ``` ### Technical Analysis The third command-line argument is assigned directly to `ARG` and then evaluated by Bash arithmetic comparison operators: ```bash ARG="${3:-}" ``` The `-lt` and `-gt` operators place their operands in an arithmetic evaluation context. Bash arithmetic expressions can recursively resolve variable references and evaluate array subscripts. A value containing a crafted arithmetic expression may therefore cause command substitutions embedded in an array subscript to execute. The code checks only whether the resulting arithmetic value is between 0 and 100. It does not first require the input to consist exclusively of decimal digits. ### Attack Path 1. An attacker obtains the ability to invoke the script or influence the volume argument passed by an automation layer. 2. The attacker supplies a malicious arithmetic expression instead of an ordinary numeric volume, for example an expression containing a command substitution in an array subscript. 3. The expression reaches the following comparison without lexical validation: ```bash [[ "$ARG" -lt 0 || "$ARG" -gt 100 ]] ``` 4. Bash evaluates the expression and executes the embedded command substitution. 5. The command runs with the operating-system privileges and environment of the user executing the Skill. This is a local command-execution path. Exploitation requires control over the volume argument but does not require modifying the script. ### Impact Assessment Successful exploitation can execute arbitrary shell commands with the privileges of the Skill process. This could permit access to the invoking user's files and credentials, modification of user-owned data, outbound network access, and ...[truncated 180 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Require a strict decimal representation before entering any arithmetic context: ```bash if [[ ! "$ARG" =~ ^[0-9]+$ ]]; then echo "Error: Volume must be an integer from 0 to 100" exit 1 fi if (( 10#$ARG > 100 )); then echo "Error: Volume must be an integer from 0 to 100" exit 1 fi ``` The `10#` prefix forces base-10 interpretation and avoids octal handling of values with leading zeroes. Apply the same strict validation to every user-controlled value used in arithmetic expressions or JSON request bodies. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/spotify.sh:56
Finding
Spotify OAuth Secrets Exposed in Process Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/spotify.sh:56-58` and `scripts/spotify.sh:115-117` **Vulnerability Type**: Sensitive information exposure through process arguments **Risk Level**: Medium ### Vulnerable Code Refresh-token request: ```bash local response=$(curl -s -X POST "https://accounts.spotify.com/api/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=refresh_token&refresh_token=$refresh_token&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET") ``` Authorization-code exchange: ```bash local response=$(curl -s -X POST "https://accounts.spotify.com/api/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code&code=$code&redirect_uri=$REDIRECT_URI&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET") ``` ### Technical Analysis The OAuth client secret, refresh token, and authorization code are expanded directly into `curl` command-line arguments. While the requests are transmitted to Spotify over HTTPS, transport encryption does not protect secrets exposed locally in the process argument vector. Depending on the operating-system configuration, same-host users, process-monitoring agents, diagnostic utilities, audit systems, crash collectors, or command telemetry may be able to observe and retain the expanded `curl` arguments. The refresh token is particularly sensitive because it can remain valid beyond the short lifetime of an access token and can be exchanged for new access tokens. ### Attack Path 1. The user runs `spotify.sh auth` or an operation that causes an expired token to be refreshed. 2. The script starts `curl` with the client secret and OAuth token material embedded in its argument vector. 3. A local observer or monitoring component inspects the process list or records process-execution arguments while `curl` is running. 4. The observer extracts the client secret, authorization code, or refresh token. 5. Captured reusable credent ...[truncated 811 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not place secrets in command-line arguments. Construct the form body and provide it to `curl` over standard input: ```bash response=$( printf '%s' \ "grant_type=refresh_token&refresh_token=$refresh_token&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET" | curl -sS -X POST "https://accounts.spotify.com/api/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-binary @- ) ``` Apply the same pattern to the authorization-code exchange. Additional hardening should include: - Use `--data-urlencode` semantics when constructing form fields so special characters cannot corrupt the request. - Avoid verbose shell tracing while secrets are in scope. - Unset sensitive variables after use where practical. - Ensure monitoring and error handling never log complete OAuth responses or request bodies. - Prefer OAuth flows that do not require distributing a reusable client secret when supported by the application model. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/spotify.sh:69
Finding
Spotify Access and Refresh Tokens Written Without Enforced Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/spotify.sh:69-73` and `scripts/spotify.sh:124` **Vulnerability Type**: Insecure storage permissions for authentication tokens **Risk Level**: Medium ### Vulnerable Code Token refresh writes through a temporary file and replaces the token file: ```bash jq --arg at "$access_token" \ --arg ea "$((now + expires_in - 60))" \ --arg rt "${new_refresh:-$refresh_token}" \ '.access_token = $at | .expires_at = ($ea | tonumber) | .refresh_token = $rt' \ "$SPOTIFY_TOKEN" > "${SPOTIFY_TOKEN}.tmp" && mv "${SPOTIFY_TOKEN}.tmp" "$SPOTIFY_TOKEN" ``` Initial authentication writes the OAuth response directly: ```bash echo "$response" | jq --arg ea "$((now + expires_in - 60))" '. + {expires_at: ($ea | tonumber)}' > "$SPOTIFY_TOKEN" ``` The storage paths are configured as follows: ```bash CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/clawdbot" SPOTIFY_CREDS="$CONFIG_DIR/spotify.json" SPOTIFY_TOKEN="$CONFIG_DIR/spotify_token.json" ``` ### Technical Analysis The token file contains an access token and normally a reusable refresh token. The script creates and replaces this file without setting a restrictive process umask, explicitly creating the file with mode `0600`, or validating permissions on the containing directory. Consequently, the resulting permissions depend on the caller's current umask and pre-existing directory configuration. With a permissive umask, the token or temporary token file can be group-readable or world-readable. The temporary file used during refresh creates an additional exposure point. The same configuration directory also contains `spotify.json`, which the documented setup expects to hold the Spotify client secret, but the script does not validate that file's permissions. ### Attack Path 1. A user runs the authentication flow under a permissive umask or with an inadequately protected configuration directory. 2. The script writes `spotify_token.json` or `spotify_token.jso ...[truncated 892 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Set restrictive permissions before creating any credential or token files: ```bash umask 077 mkdir -p "$CONFIG_DIR" chmod 700 "$CONFIG_DIR" ``` Create temporary files securely inside the protected directory and enforce mode `0600`: ```bash tmp_file=$(mktemp "$CONFIG_DIR/spotify_token.json.XXXXXX") chmod 600 "$tmp_file" jq --arg at "$access_token" \ --arg ea "$((now + expires_in - 60))" \ --arg rt "${new_refresh:-$refresh_token}" \ '.access_token = $at | .expires_at = ($ea | tonumber) | .refresh_token = $rt' \ "$SPOTIFY_TOKEN" > "$tmp_file" mv -f "$tmp_file" "$SPOTIFY_TOKEN" chmod 600 "$SPOTIFY_TOKEN" ``` Also: - Verify that `$CONFIG_DIR`, `spotify.json`, and `spotify_token.json` are owned by the current user and are not symbolic links. - Reject unsafe permissions rather than silently continuing. - Install a trap to remove temporary files on failure or interruption. - Recommend revoking and regenerating tokens if prior files may have been readable by other users. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (37)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
If the implementation truly uses Spotify OAuth, token storage, and Spotify Web APIs as described by the finding, that would materially exceed the stated Devialet HTTP-control scope and introduce credential-handling risk. However, this specific SKILL.md content does not clearly show OAuth flows or token storage, so part of the finding appears overstated relative to the visible file.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the implementation truly uses Spotify OAuth, token storage, and Spotify Web APIs as described by the finding, that would materially exceed the stated Devialet HTTP-control scope and introduce credential-handling risk. However, this specific SKILL.md content does not clearly show OAuth flows or token storage, so part of the finding appears overstated relative to the visible file.

Ae1

High
Category
analysis-evasion
Content
./scripts/play-on-devialet.sh "Drake - God's Plan"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/play-on-devialet.sh "Drake - God's Plan"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/play-on-devialet.sh "Drake - God's Plan"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/play-on-devialet.sh "Drake - God's Plan"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/play-on-devialet.sh "Drake - God's Plan"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
./scripts/play-on-devialet.sh "Drake - God's Plan"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The script materially expands the stated Devialet HTTP API skill into Spotify OAuth and remote Spotify account/device control, which is outside the declared purpose. This mismatch is dangerous because users may grant third-party account permissions and execute unintended internet-connected actions under the assumption they are only controlling local speakers.

Credential Access

High
Category
Privilege Escalation
Content
CLIENT_SECRET=$(jq -r '.client_secret' "$SPOTIFY_CREDS")
}

# Get valid access token (refresh if needed)
get_token() {
    if [[ ! -f "$SPOTIFY_TOKEN" ]]; then
        echo "Error: Not authenticated. Run: $0 auth"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill documents shell-based execution paths (`curl`, script invocation, package installation) but declares no explicit tool scope or allowed-tools boundary. In an agent environment, this broadens what the agent may attempt without least-privilege constraints, increasing the risk of unintended command execution or network actions beyond the stated purpose.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest description omits the documented Spotify search/play functionality, which means users and reviewers are not given an accurate picture of the skill's external-service interactions. Hidden or under-disclosed capability is a security concern because it can lead to inappropriate approval of network, desktop, or account-linked behavior.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The manifest presents the skill as HTTP-based speaker control, while the body explains that playback works by searching in Spotify and opening URIs in the Spotify app. This discrepancy can mislead operators about the trust boundary, causing them to underestimate external-service usage, local application control, and data flow outside the local network.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The documentation introduces `playerctl` and `xdotool`, which enable control of local desktop media sessions and GUI automation, far beyond a narrow speaker HTTP API. In context, this increases the attack surface from a LAN device controller to a local workstation automation tool, which can be abused to manipulate user applications or input.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- **Devialet speaker** with DOS 2.14+ or SDOS 1.3+ firmware
- **Spotify integration** (optional):
  - Spotify desktop app running and logged in
  - `playerctl` and `xdotool` installed (`sudo apt install playerctl xdotool`)
  - Speaker set as Spotify Connect device (select once in Spotify app)

## How It Works
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Volume (0-100)
curl -X POST -H "Content-Type: application/json" \
  -d '{"volume": 50}' \
  "http://$DEVIALET_IP/ipcontrol/v1/systems/current/sources/current/soundControl/volume"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation exposes that the device control API uses plain HTTP and requires no authentication, enabling anyone on the same network segment to issue state-changing commands such as volume changes, source switching, mute, playback control, and power-off. In a skill context that helps users operate these endpoints, the lack of a prominent security warning increases the likelihood of unsafe deployment on shared or untrusted networks, leading to unauthorized device manipulation and privacy or availability issues.

External Transmission

Medium
Category
Data Exfiltration
Content
post() {
    local endpoint="$1"
    local data="${2:-{}}"
    curl -s -H 'Content-Type: application/json' -X POST -d "$data" "${BASE_URL}${endpoint}" | $FORMAT
}

# Handle discover command specially (no host required)
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest describes controlling Devialet Phantom speakers via the Devialet HTTP API for play/pause, volume, mute/unmute, source selection, and status. This script also automates a local Spotify client via D-Bus/playerctl/xdotool, performs Google web searches for tracks, and opens Spotify URIs, which is broader than merely controlling the speaker through its HTTP API.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The script sends user-provided song queries to Google, which transmits potentially sensitive listening intent or user-entered text to an unrelated third party outside the stated Devialet control scope. This creates an unexpected data disclosure channel and broadens the trust boundary, especially because users may assume only local speaker control is occurring.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
Using xdotool to inject a Return key into the active GUI session can affect whichever window has focus, not necessarily Spotify, causing unintended actions in other applications. In a desktop automation context this is dangerous because it crosses application boundaries and can trigger unpredictable user-interface side effects without robust targeting or consent.

External Transmission

Medium
Category
Data Exfiltration
Content
volume|vol)
        if [[ -n "$ARG2" ]]; then
            echo "Setting volume to $ARG2%"
            curl -s -X POST -H "Content-Type: application/json" \
                -d "{\"volume\": $ARG2}" \
                "http://$DEVIALET_IP/ipcontrol/v1/systems/current/sources/current/soundControl/volume" &>/dev/null
            echo "Volume: $ARG2%"
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
load_creds
        local refresh_token=$(jq -r '.refresh_token' "$SPOTIFY_TOKEN")
        
        local response=$(curl -s -X POST "https://accounts.spotify.com/api/token" \
            -H "Content-Type: application/x-www-form-urlencoded" \
            -d "grant_type=refresh_token&refresh_token=$refresh_token&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
load_creds
        local refresh_token=$(jq -r '.refresh_token' "$SPOTIFY_TOKEN")
        
        local response=$(curl -s -X POST "https://accounts.spotify.com/api/token" \
            -H "Content-Type: application/x-www-form-urlencoded" \
            -d "grant_type=refresh_token&refresh_token=$refresh_token&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The OAuth flow introduces third-party account authorization and persistent control over a user's Spotify playback without that capability being justified by the advertised Devialet-only purpose. In skill ecosystems, undeclared account-linking behavior increases phishing, overpermission, and user-consent risk because users are not expecting external credential workflows.

Static analysis

No suspicious patterns detected.