Back to skill

Security audit

save-to-spotify

Security checks for vulnerabilities and agentic risk

Overview

This audio-production skill needs review because it can inspect connected work accounts and send derived content to cloud services without clearly establishing those boundaries first.

Specify which calendars, repositories, and task accounts the agent may read before using personalized recipes. Confirm which speech and image providers may receive your content; private Spotify visibility does not mean all processing stays local. Follow the skill's prohibition on confidential uploads. Prefer a verified, versioned CLI installed locally, and review installer side effects before bypassing executable warnings. The remote installer and compiled CLI remain outside the verified artifact bundle.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (34)

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

The installation command executes a mutable remote script immediately, without an independently verified signature or pinned digest. User confirmation and the Spotify-associated HTTPS hostname reduce suspicion but do not prevent a compromised distribution endpoint from executing arbitrary code with the agent's local privileges.

Content

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

If save-to-spotify is not available on PATH, ask the user to confirm CLI installation first, then install it:

shell
curl -fsSL https://saveto.spotify.com/install.sh | bash

On Windows, run this in Git Bash (ships with Git for Windows) — it installs save-to-spotify.exe to ~/.local/bin. The unsigned .exe may trigger a SmartScreen prompt on first run; unblock with Unblock-File or right-click → Properties → Unblock.

Chaining Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

Piping the HTTP response directly into bash turns remotely supplied content into executable commands without an intervening verification step. This is the same installation vulnerability identified by SC2, not evidence of a separate malicious tool chain.

Content

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

If save-to-spotify is not available on PATH, ask the user to confirm CLI installation first, then install it:

shell
curl -fsSL https://saveto.spotify.com/install.sh | bash

On Windows, run this in Git Bash (ships with Git for Windows) — it installs save-to-spotify.exe to ~/.local/bin. The unsigned .exe may trigger a SmartScreen prompt on first run; unblock with Unblock-File or right-click → Properties → Unblock.

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

The recommended installation command executes a mutable remote script immediately without independently verifying it. HTTPS and the claimed binary checksum verification do not authenticate the installer itself; compromise of its delivery path could execute attacker-controlled code with the invoking user's privileges.

Content

Scanner excerpt · references/cli-usage.md (reported line 12)May include surrounding context.

One-line install (recommended)

shell
curl -fsSL https://saveto.spotify.com/install.sh | bash

Detects OS and architecture, downloads the binary from GitHub Releases, verifies the SHA256 checksum, and installs to /usr/local/bin (or ~/.local/bin if not writable).

Chaining Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

The pipeline converts remotely supplied content directly into shell instructions without an intervening verification step. This is the same remote-code-execution exposure reported by SC2 at line 12, not an additional independent vulnerability or evidence of malicious intent.

Content

Scanner excerpt · references/cli-usage.md (reported line 12)May include surrounding context.

One-line install (recommended)

shell
curl -fsSL https://saveto.spotify.com/install.sh | bash

Detects OS and architecture, downloads the binary from GitHub Releases, verifies the SHA256 checksum, and installs to /usr/local/bin (or ~/.local/bin if not writable).

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

Specifying a binary version does not pin or authenticate the remote installer that is piped into bash. A compromised installer can run arbitrary commands before or instead of installing the requested release.

Content

Scanner excerpt · references/cli-usage.md (reported line 21)May include surrounding context.

shell
# Specific version
curl -fsSL https://saveto.spotify.com/install.sh | bash -s -- --version 0.2.1

# Custom directory
curl -fsSL https://saveto.spotify.com/install.sh | bash -s -- --dir ~/.local/bin

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

Choosing ~/.local/bin changes the intended installation destination but does not sandbox the script fetched and executed by bash. A compromised response could still access the user's files, credentials, and network permissions.

Content

Scanner excerpt · references/cli-usage.md (reported line 24)May include surrounding context.

md
curl -fsSL https://saveto.spotify.com/install.sh | bash -s -- --version 0.2.1

# Custom directory
curl -fsSL https://saveto.spotify.com/install.sh | bash -s -- --dir ~/.local/bin

# Via environment variables
SAVE_TO_SPOTIFY_VERSION=0.2.1 SAVE_TO_SPOTIFY_INSTALL_DIR=~/.local/bin \

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

This environment-variable variant still pipes an unverified remote script directly into bash. Configuration variables do not constrain what the downloaded script can execute, so compromise could expose local data and credentials.

Content

Scanner excerpt · references/cli-usage.md (reported line 28)May include surrounding context.

Via environment variables

SAVE_TO_SPOTIFY_VERSION=0.2.1 SAVE_TO_SPOTIFY_INSTALL_DIR=~/.local/bin
curl -fsSL https://saveto.spotify.com/install.sh | bash

text

### Download a binary manually

Chaining Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

The curl-to-bash chain executes the network response as code with the agent's user privileges. This duplicates the SC2 finding at line 28 and could enable credential theft or local modification if the installer distribution is compromised.

Content

Scanner excerpt · references/cli-usage.md (reported line 28)May include surrounding context.

Via environment variables

SAVE_TO_SPOTIFY_VERSION=0.2.1 SAVE_TO_SPOTIFY_INSTALL_DIR=~/.local/bin
curl -fsSL https://saveto.spotify.com/install.sh | bash

text

### Download a binary manually

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/cli-usage.md (reported line 140)May include surrounding context.

Environment token (skip OAuth entirely)

If the user already has a Spotify access token (e.g. from another tool or CI secret):

shell
export SAVE_TO_SPOTIFY_AUTH_TOKEN="BQD..."

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/cli-usage.md (reported line 158)May include surrounding context.

Token refresh is automatic -- if the saved token is expired, the CLI refreshes it silently on the next command. No action needed unless the refresh token itself is revoked, in which case the user must auth login again.

Print the access token

shell
save-to-spotify token

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/cli-usage.md (reported line 164)May include surrounding context.

save-to-spotify token

text

Prints the current access token to stdout -- directly usable as a **Spotify Web API bearer** for requests against `api.spotify.com`. Useful for catalog lookups (searching album/track URIs, fetching release metadata) from inside recipes. Exits non-zero and prints a diagnostic to stderr when the stored token cannot be refreshed. Always check the exit code before piping into an `Authorization` header -- otherwise an empty token produces a misleading HTTP 400 from Spotify rather than a clean auth error.

See [spotify-api.md](spotify-api.md) for the official `developer.spotify.com` references, OpenAPI spec URL, endpoint patterns, and URI-resolution helpers.

External Script Fetching

High
Category
Supply Chain
Confidence
98% confidence
Finding

The onboarding command downloads and immediately executes a mutable shell script. The claim that the installer verifies the binary does not authenticate the installer itself, so a compromised script endpoint could execute arbitrary local commands.

Content

Scanner excerpt · references/onboarding.md (reported line 38)May include surrounding context.

Goal: CLI installed and on PATH.

text
curl -fsSL https://saveto.spotify.com/install.sh | bash

On Windows, run it in Git Bash. The installer downloads the binary, verifies it, and prints:

Chaining Abuse

High
Category
Tool Misuse
Confidence
98% confidence
Finding

The pipe directly crosses the boundary between downloaded content and shell execution without independent verification. This overlaps the SC2 finding on the same command and creates a supply-chain execution risk rather than demonstrating malicious intent.

Content

Scanner excerpt · references/onboarding.md (reported line 38)May include surrounding context.

Goal: CLI installed and on PATH.

text
curl -fsSL https://saveto.spotify.com/install.sh | bash

On Windows, run it in Git Bash. The installer downloads the binary, verifies it, and prints:

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/spotify-api.md (reported line 27)May include surrounding context.

md
## Getting a bearer token

`save-to-spotify token` prints the current access token to stdout. That token has been verified to work as a Spotify Web API `Bearer` token for requests against `api.spotify.com`, so agents do not need a separate app registration for the catalog lookups below.

Guard the call because it exits non-zero when the stored token cannot be refreshed:

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
Every episode — regardless of content type — must complete these steps.

0. **Preflight: install, auth, and voice engine** — Run `save-to-spotify --json doctor` before any sourcing. This checks the binary, auth, TTS engines, and ffmpeg in one call. If the binary is missing, ask the user to confirm installation, install it with the command in the Install section after they approve, then run doctor again. If unauthenticated, run `save-to-spotify setup` directly (do not ask the user to run it — just run it). The setup command handles auth + TTS detection in one pass and auto-detects headless environments. **Then confirm a TTS engine is available** via the `tts_engines` field in the doctor output: if one is already set up or the user has a preference, use it; otherwise check for an existing API key (`OPENAI_API_KEY`, `ELEVENLABS_API_KEY`) and suggest that engine first — no install, higher quality. If no key is present, **ask the user** whether to install **Kokoro** (free, local, ~340 MB,

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/onboarding.md (reported line 55)May include surrounding context.

Goal: Spotify account connected in one action.

Run save-to-spotify setup directly — do not ask the user to run it. The agent executes this itself:

shell
save-to-spotify setup

Cloud TTS production lacks disclosure that episode text is sent to a third-party provider.

Medium
Category
Output Handling
Confidence
93% confidence
Finding

The workflow can reuse a configured cloud TTS engine without explaining that episode scripts leave the local environment. Scripts derived from voice memos, meetings, or personal documents may contain sensitive information, and approval to produce an episode does not necessarily authorize this additional disclosure.

Content

No source excerpt is available for this finding.

Cloud TTS synthesis lacks a user-facing disclosure that episode scripts are sent to an external provider.

Medium
Category
Output Handling
Confidence
94% confidence
Finding

Provider selection permits automatic reuse of a configured cloud engine, and the synthesis examples send script text to external services. Naming a provider or finding an existing API key does not establish informed permission to transmit potentially confidential episode content.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · references/cli-usage.md (reported line 39)May include surrounding context.

md
# macOS Apple Silicon
gh release download --repo spotify/save-to-spotify --pattern "save-to-spotify-darwin-arm64"
chmod +x save-to-spotify-darwin-arm64
sudo mv save-to-spotify-darwin-arm64 /usr/local/bin/save-to-spotify

# macOS Intel
gh release download --repo spotify/save-to-spotify --pattern "save-to-spotify-darwin-amd64"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · references/cli-usage.md (reported line 44)May include surrounding context.

md
# macOS Intel
gh release download --repo spotify/save-to-spotify --pattern "save-to-spotify-darwin-amd64"
chmod +x save-to-spotify-darwin-amd64
sudo mv save-to-spotify-darwin-amd64 /usr/local/bin/save-to-spotify

# Linux x86_64
gh release download --repo spotify/save-to-spotify --pattern "save-to-spotify-linux-amd64"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · references/cli-usage.md (reported line 49)May include surrounding context.

Linux x86_64

gh release download --repo spotify/save-to-spotify --pattern "save-to-spotify-linux-amd64" chmod +x save-to-spotify-linux-amd64 sudo mv save-to-spotify-linux-amd64 /usr/local/bin/save-to-spotify

text

### Build from source

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · references/cli-usage.md (reported line 60)May include surrounding context.

git clone https://github.com/spotify/save-to-spotify.git && cd save-to-spotify go build -ldflags "-X github.com/spotify/save-to-spotify/cmd.commit=$(git rev-parse --short HEAD)"
-o save-to-spotify . sudo mv save-to-spotify /usr/local/bin/

text

Verify installation:

Default AI image generation sends topic-derived information to an external provider without a privacy warning.

Medium
Category
Output Handling
Confidence
93% confidence
Finding

The default cover-generation path can send topic-derived prompts to an external image provider without explaining that transfer. Even a short concrete-subject prompt can reveal confidential projects or personal interests; restricting generation to known providers does not resolve the consent gap.

Content

No source excerpt is available for this finding.

Cloud TTS generation lacks a warning that episode scripts are sent to an external provider.

Medium
Category
Output Handling
Confidence
94% confidence
Finding

The onboarding flow obtains approval for a voice and generation but does not explain that a cloud engine receives the episode script. This matters particularly for briefings drawn from calendar, repository, and task data, while the repeated assurances of private Spotify storage do not describe upstream processing.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/onboarding.md (reported line 238)May include surrounding context.

md
## Design principles

1. **Always present choices, never ask for free text** — every decision point must be a list of options the user can pick from. Never ask the user to type something. Open-ended text input breaks the flow and creates friction. If you need input, present smart options and let them pick. And embed whatever the user is judging (chapter list, preview URL, file link) **inside the choice prompt itself** — plain text printed before a choice popup can be hidden by it, leaving the user a question about content they never saw
2. **Content before audio** — chapters are approved and the script written before any voice or audio work. Iterating on text costs nothing; regenerating audio does
3. **Show, don't tell** — script summaries, voice previews, and a local browser preview of the finished episode
4. **Default everything** — language, length, voice, cover, show, and content topic all have smart defaults