Back to skill

Security audit

Spotify Controller

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real Spotify controller, but its setup guidance is too loose around dependency installation and file permissions while handling Spotify tokens.

Review before installing. Use an isolated virtual environment or locked container dependency set, pin requests, avoid system-wide package installs where possible, set the script read-only for non-deployment users such as 0644 or stricter, protect the .env file, and revoke or rotate the Spotify refresh token if it is exposed.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:41
Finding

Unpinned Third-Party Dependency Installed into the System Python Environment

Content
View full analysis
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Warning
Location
SKILL.md:116
Finding

Group-Writable Spotify Controller Script Enables Local Tool Replacement

Content
View full analysis
: /path/to/workspace/spotify.py chmod 664 /path/to/workspace/spotify.py ``` ### Technical Analysis File mode `664` grants write permission to both the owner and every member of ``. The affected file is executable application logic that is subsequently invoked with: ```bash python3 spotify.py ``` Any user or process with membership in the assigned group can alter or replace the script. The modified file would retain the expected name and invocation pattern, causing legitimate-looking Spotify commands to execute attacker-controlled Python code. This becomes particularly significant because the script runs in an environment containing three Spotify credentials. A replacement script could read these variables, misuse them, or execute other operations with the runtime user’s local permissions. The issue requires an attacker to already possess write access through the selected runtime group. It does not independently grant remote access or elevated operating-system privileges. ### Attack Path 1. The administrator follows the documentation and assigns `spotify.py` mode `664`. 2. An attacker controls another account or process that belongs to ``. 3. The attacker modifies `/path/to/workspace/spotify.py` while preserving its expected filename. 4. A user, automation, or AI agent invokes `python3 spotify.py `. 5. The injected Python code executes with the invoking runtime user’s privileges. 6. The injected code can read the Spotify environment variables and perform local or network actions available to that account. ### Impact Assessment Successful exploitation allows code execution as the account invoking the Spotify controller. The resulting scope can include: - Theft or m ...[truncated 495 chars]
Remediation
View remediation
: /path/to/workspace/spotify.py chmod 644 /path/to/workspace/spotify.py ``` 2. If the runtime user does not need to modify application code, assign ownership to a dedicated deployment account or root and grant the runtime user read-only access. 3. Ensure the parent directory is also not writable by untrusted users or shared groups. 4. Mount deployed application code read-only in containers. 5. Use a narrowly scoped group containing only trusted deployment identities. 6. Verify application-file hashes or signatures before execution in sensitive deployments. 7. Keep credentials separate from writable workspace content and expose them only to the process that requires them. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (7)

Tainted flow: 'REFRESH_TOKEN' from os.environ.get (line 23, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/spotify.py (reported line 47)May include surrounding context.

python
def get_access_token() -> str:
    ensure_env()
    r = requests.post(
        "https://accounts.spotify.com/api/token",
        data={
            "grant_type": "refresh_token",

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The code substantially matches the declared Spotify playback/device-control purpose and uses the Spotify Web API as described. Implemented commands cover status, play/pause, next/prev, volume, search, play first search result, device listing, and active-device switching. However, the description specifically claims it can 'play a specific Spotify URL,' while the implementation only accepts a track URI string for the playtrack command (e.g. spotify:track:...). There is no logic to accept or normalize open.spotify.com URLs or other Spotify URL forms. No significant undeclared capabilities are present beyond standard token refresh and API communication.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill clearly requires environment secret access and outbound network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. In an agent ecosystem, missing scope declarations weaken isolation and review controls, making it easier for the skill to access secrets or make remote requests without transparent operator approval.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 81)May include surrounding context.

Exchange code for tokens:

bash
curl -s -X POST "https://accounts.spotify.com/api/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&code=YOUR_CODE&redirect_uri=http://127.0.0.1:8888/callback&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 117)May include surrounding context.

bash
chown <runtime_user>:<runtime_group> /path/to/workspace/spotify.py
chmod 664 /path/to/workspace/spotify.py

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/spotify.py (reported line 47)May include surrounding context.

python
def get_access_token() -> str:
    ensure_env()
    r = requests.post(
        "https://accounts.spotify.com/api/token",
        data={
            "grant_type": "refresh_token",

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/spotify.py (reported line 70)May include surrounding context.

python
token = get_access_token()
    headers = kwargs.pop("headers", {})
    headers["Authorization"] = f"Bearer {token}"
    url = f"https://api.spotify.com/v1{endpoint}"
    return requests.request(method, url, headers=headers, timeout=20, **kwargs)