Back to skill

Security audit

Soundcloud

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do the advertised SoundCloud work, but it stores long-lived account tokens in plaintext while claiming encryption and exposes account-changing actions that need careful user control.

Review before installing. Use this only if you are comfortable granting SoundCloud account authority for playlist, like, and follow changes. Avoid --force and --no-confirm in agent workflows, verify playlist and track IDs before write actions, and prefer a secure credential store or short-lived/revocable tokens instead of the documented plaintext cache or shell-profile persistence.

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 (4)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth_soundcloud.sh:45
Finding

OAuth State Is Generated but Never Validated

Content
View full analysis
/dev/null 2>&1; then STATE=$(openssl rand -hex 12 2>/dev/null || echo "sc$(date +%s)") else STATE="sc$(date +%s)$$" fi AUTH_URL="${AUTH_ENDPOINT}?client_id=${SOUNDCLOUD_CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=${SCOPES}&state=${STATE}" ``` The callback extracts the returned state but does not validate it: ```python if parsed.path == '/callback': code = params.get('code', [None])[0] state_val = params.get('state', [None])[0] error = params.get('error', [None])[0] self.send_response(200) self.send_header('Content-type', 'text/html; charset=utf-8') self.end_headers() if error: self.wfile.write(f'''

Authorization Failed

Error: {error}

You can close this window.

'''.encode()) print(f'ERROR:{error}', flush=True) elif code: self.wfile.write(f'''

✓ Authorization Successful!

You can close this window and return to your terminal.

'''.encode()) print(f'CODE:{code}', flush=True) if state_val: print(f'STATE:{state_val}', flush=True) ``` The script instead accepts an independently pasted code and exchanges it without checking state: ```bash echo -e "${YELLOW}Or, paste the authorization code here:${NC}" echo -n "> " read -r AUTH_CODE kill $SERVER_PID 2>/dev/null || true if [ -z "$AUTH_CODE" ]; then ech ...[truncated 2187 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth_token.sh:91
Finding

OAuth Tokens Are Cached in Plaintext Despite an Encryption-at-Rest Claim

Content
View full analysis
"$output_file" chmod 600 "$output_file" } ``` User tokens are stored in the same plaintext format: ```bash save_user_token() { local access_token="$1" local refresh_token="${2:-}" local expires_in="${3:-21599}" local now expires_at now=$(date +%s) expires_at=$((now + expires_in)) jq -n \ --arg access_token "$access_token" \ --argjson expires_at "$expires_at" \ --arg refresh_token "${refresh_token}" \ --arg token_type "bearer" \ '{ access_token: $access_token, expires_at: $expires_at, refresh_token: $refresh_token, token_type: $token_type }' > "$USER_TOKEN_FILE" chmod 600 "$USER_TOKEN_FILE" echo -e "${GREEN}✓ User token saved${NC}" >&2 } ``` The documentation incorrectly describes this storage as encrypted: ```text - Caches it at `~/.cache/soundclo ...[truncated 1939 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
references/oauth_flow.md:130
Finding

Security Documentation Recommends Unsafe Plaintext Credential Persistence and Shell Parsing

Content
View full analysis
> .env ``` It also writes a client secret to `.env` with default filesystem permissions: ```bash read -sp "Enter SoundCloud Client ID: " client_id echo read -sp "Enter SoundCloud Client Secret: " client_secret echo # Save to .env file cat > .env << EOF SOUNDCLOUD_CLIENT_ID=$client_id SOUNDCLOUD_CLIENT_SECRET=$client_secret EOF ``` The reference loads this file using shell word splitting: ```bash if [ -f .env ]; then export $(cat .env | grep -v '^#' | xargs) fi ``` It later appends live tokens to the same file: ```bash echo "SOUNDCLOUD_ACCESS_TOKEN=$ACCESS_TOKEN" >> .env if [ -n "$REFRESH_TOKEN" ]; then echo "SOUNDCLOUD_REFRESH_TOKEN=$REFRESH_TOKEN" >> .env fi ``` The best-practices document repeats the unsafe loading pattern: ```bash # Load config if [ -f "$CONFIG_FILE" ]; then export $(grep -v '^#' "$CONFIG_FILE" | xargs) fi # Set defaults export SOUNDCLOUD_CLIENT_ID=${SOUNDCLOUD_CLIENT_ID:-""} export SOUNDCLOUD_ACCESS_TOKEN=${SOUNDCLOUD_ACCESS_TOKEN:-""} ``` It also stores a newly obtained token as plaintext: ```bash NEW_TOKEN=$(curl -s -X POST "https://api.soundcloud.com/oauth2/token" \ -d "client_id=$CLIENT_ID" \ -d "client_secret=$CLIENT_SECRET" \ -d "grant_type=refresh_token" \ -d "refresh_token=$REFRE ...[truncated 2602 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/analyze_track.sh:33
Finding

Unencoded User Input Can Inject Additional SoundCloud API Query Parameters

Content
View full analysis
/dev/null 2>&1; then echo "$response" | jq -r '.id' return 0 else echo -e "${RED}Error: Could not resolve URL '$input'${NC}" >&2 return 1 fi else echo -e "${RED}Error: Invalid input. Provide a track ID or SoundCloud URL${NC}" >&2 return 1 fi } ``` The shared request wrapper concatenates the path into the request URL: ```bash sc_api_get() { local path="$1" local token token=$(get_app_token) || return 1 curl -s -L -X GET "https://api.soundcloud.com${path}" \ -H "Authorization: Bearer ${token}" \ -H "accept: application/json; charset=utf-8" } ``` Related call sites construct resolve queries the same way: ```bash RESOLVED=$(sc_api_get "/resolve?url=https://soundcloud.com/${USER_INPUT}") ``` ```bash response=$(sc_api_get "/resolve?url=https://soundcloud.com/${identifier}") ``` ```bash RESOLVED=$(sc_api_get "/resolve?url=${TRACK_INPUT}") ``` ### Technical Analysis The track URL is considered valid whenever it contains the substring `soundcloud.com`; it is not required to use HTTPS, have `soundcloud.com` as its actual host, or conform to an expected SoundCloud path. The value is inserted into the `url` query parameter without percent encoding. Characters such as `&`, `#`, and `=` retain URL ...[truncated 1651 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (116)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
86% confidence
Finding

A no-confirm flag on a script that performs authenticated write actions creates a tool-parameter abuse path: an agent or attacker influencing the agent can suppress safety interlocks and modify the user's SoundCloud account without meaningful consent. Because this skill supports authenticated playlist and social actions, the context makes bypassing confirmations materially more dangerous than in a read-only skill.

Content

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

Create a new playlist (requires user token).

bash
./scripts/create_playlist.sh "Playlist Name" [--description "text"] [--tracks "id1,id2"] [--sharing public|private] [--genre "genre"] [--tags "tag1,tag2"] [--no-confirm]

scripts/update_playlist.sh

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
94% confidence
Finding

DELETE /playlists/{playlist_id} is an account-modifying destructive operation that can be triggered if untrusted input is mapped directly to tool parameters. In an agent setting, prompt injection, misunderstanding, or ID confusion could cause irreversible deletion of a user's playlist.

Content

Scanner excerpt · references/api_endpoints.md (reported line 115)May include surrounding context.

Delete Playlist (Authenticated)

text
DELETE /playlists/{playlist_id}

Users

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
88% confidence
Finding

DELETE /me/favorites/{track_id} changes the user's account state by removing a liked track. While less severe than deleting content, it is still vulnerable to unsafe parameter use and unintended actions if the agent acts on untrusted instructions or ambiguous IDs.

Content

Scanner excerpt · references/api_endpoints.md (reported line 188)May include surrounding context.

Like/Unlike Track

text
PUT /me/favorites/{track_id}    # Like
DELETE /me/favorites/{track_id} # Unlike

Follow/Unfollow User

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
89% confidence
Finding

DELETE /me/followings/{user_id} unfollows another user and modifies the authenticated account. In an agent skill, this can be abused through prompt injection or accidental parameter substitution, causing unauthorized social/account changes without clear user intent.

Content

Scanner excerpt · references/api_endpoints.md (reported line 194)May include surrounding context.

Follow/Unfollow User

text
PUT /me/followings/{user_id}    # Follow
DELETE /me/followings/{user_id} # Unfollow

Repost Track

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/best_practices.md (reported line 311)May include surrounding context.

md
case $ENV in
    production)
        CONFIG_FILE=".env.production"
        ;;
    staging)
        CONFIG_FILE=".env.staging"

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/best_practices.md (reported line 317)May include surrounding context.

md
CONFIG_FILE=".env.staging"
        ;;
    *)
        CONFIG_FILE=".env.development"
        ;;
esac

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/oauth_flow.md (reported line 5)May include surrounding context.

md
## Overview

SoundCloud uses OAuth 2.0 for authenticated API access. This guide covers the complete authentication flow for obtaining access tokens to perform user-specific actions like creating playlists, liking tracks, and accessing private data.

## Prerequisites

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/best_practices.md (reported line 632)May include surrounding context.

text

#### Step 4: Exchange Code for Token
Exchange the authorization code for an access token:

```bash
curl -X POST "https://api.soundcloud.com/oauth2/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/oauth_flow.md (reported line 65)May include surrounding context.

text

#### Step 4: Exchange Code for Token
Exchange the authorization code for an access token:

```bash
curl -X POST "https://api.soundcloud.com/oauth2/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/oauth_flow.md (reported line 220)May include surrounding context.

text

#### Step 4: Exchange Code for Token
Exchange the authorization code for an access token:

```bash
curl -X POST "https://api.soundcloud.com/oauth2/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/oauth_flow.md (reported line 274)May include surrounding context.

text

#### Step 4: Exchange Code for Token
Exchange the authorization code for an access token:

```bash
curl -X POST "https://api.soundcloud.com/oauth2/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/oauth_flow.md (reported line 86)May include surrounding context.

}

text

#### Step 5: Use Access Token
Include token in API requests:
```bash
curl -X GET "https://api.soundcloud.com/me" \

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/oauth_flow.md (reported line 111)May include surrounding context.

}

text

#### Step 5: Use Access Token
Include token in API requests:
```bash
curl -X GET "https://api.soundcloud.com/me" \

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/oauth_flow.md (reported line 238)May include surrounding context.

}

text

#### Step 5: Use Access Token
Include token in API requests:
```bash
curl -X GET "https://api.soundcloud.com/me" \

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 136)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 137)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 150)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 151)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 170)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 171)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 177)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 253)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 351)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 352)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/oauth_flow.md (reported line 358)May include surrounding context.

DO NOT commit tokens to version control

DO store in environment variables or secure vault

Good practice: Use .env file (add to .gitignore)

echo "SOUNDCLOUD_ACCESS_TOKEN=your_token" >> .env

text