Back to skill

Security audit

Apple Music DJ

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Apple Music playlist helper, but its optional cron automation installs persistent commands in an unsafe way that needs review before use.

Install only if you are comfortable granting Apple Music library access and local profile caching. Avoid the cron automation until setup_cron.py quotes and validates crontab fields and creates private log files; if you do use it, provide only trusted simple paths/storefront values and review the installed crontab.

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/setup_cron.py:49
Finding
Persistent Shell Command Injection in Generated Crontab Entries<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup_cron.py:49-96` **Vulnerability Type**: Persistent shell command injection through unquoted cron parameters **Risk Level**: High ### Vulnerable Code ```python def build_job_defs(python: str, profile: str, sf: str, log_dir: str) -> dict[str, dict]: """Return cron job definitions keyed by job name.""" strategy = SCRIPT_DIR / "strategy_engine.py" daily_pick = SCRIPT_DIR / "daily_pick.py" new_releases = SCRIPT_DIR / "new_releases.sh" health = SCRIPT_DIR / "playlist_health.py" return { "weekly-mix": { "description": "Generate a fresh playlist every Monday at 7 AM", "schedule": "0 7 * * 1", "command": ( f"{python} {strategy} --strategy trend " f"--profile {profile} --storefront {sf} --create" ), "log": f"{log_dir}/weekly-mix.log", }, "new-releases": { "description": "Check for new releases every Wednesday at 8 AM", "schedule": "0 8 * * 3", "command": f"bash {new_releases} {sf}", "log": f"{log_dir}/new-releases.log", }, "daily-drop": { "description": "Surface a daily pick every day at 8:30 AM", "schedule": "30 8 * * *", "command": ( f"{python} {daily_pick} daily --profile {profile}" ), "log": f"{log_dir}/daily-drop.log", }, "health-check": { "description": "Scan playlists for issues on the 1st of each month", "schedule": "0 9 1 * *", "command": ( f"{python} {health} check all --profile {profile}" ), "log": f"{log_dir}/health-check.log", }, } def format_cron_line(job: dict, name: str) -> str: """Format a single crontab line with logging and marker.""" return ( f"{job['schedule']} {job[ ...[truncated 2892 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Apply `shlex.quote()` independently to every executable path, file path, storefront value, and redirection target before constructing the cron command. 2. Validate storefront values against a strict allowlist or `^[a-z]{2}$`. 3. Reject carriage returns, newline characters, NUL bytes, and other control characters in every value written to a crontab. 4. Resolve and validate executable and script paths before installation: - Require absolute paths. - Ensure expected files exist. - Reject unexpected symlinks where appropriate. 5. Construct each job from a list of arguments and use a dedicated serialization function rather than accepting an already assembled shell command. 6. Consider installing a fixed wrapper script and placing only a quoted wrapper path plus a fixed job identifier in the crontab. 7. Display the exact escaped crontab lines and require explicit confirmation before calling `crontab -`. 8. Add tests covering spaces, quotes, semicolons, command substitutions, redirections, and newline injection in all configurable fields. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/taste_profiler.py:420
Finding
Cached Taste Profiles May Be Exported with Excessive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/taste_profiler.py:420-429` **Vulnerability Type**: Insecure storage permissions for sensitive listening-profile data **Risk Level**: Medium ### Vulnerable Code ```python # Check cache first if args.cache: cached = load_cache(args.cache, args.max_age) if cached: print("Using cached taste profile.", file=sys.stderr) output = json.dumps(cached, indent=2) if args.output: Path(args.output).write_text(output) else: print(output) return ``` By comparison, the fresh-profile path uses an explicitly restricted mode: ```python fd = _os.open(str(args.output), _os.O_WRONLY | _os.O_CREAT | _os.O_TRUNC, 0o600) with _os.fdopen(fd, "w") as f: f.write(output) ``` ### Technical Analysis When a fresh profile is generated, the output file is opened with mode `0600`. When a cached profile is reused, however, `Path.write_text()` creates or truncates the destination using the process's ambient umask. On systems with a common umask such as `0022`, a newly created file may receive mode `0644`, making it readable by other local users. The behavior is inconsistent with the project's documented privacy posture and with the secure writer used elsewhere in the same script. The exported profile contains private listening-derived information, including: - Favorite artists and genre distribution. - Energy, variety, mainstream, and listening-velocity classifications. - Loved and disliked song identifiers. - Library song identifiers. - Replay-derived highlights and listening statistics. - Storefront and profile generation time. ### Attack Path 1. The user has a valid taste-profile cache. 2. The user invokes the profiler with both `--cache` and `--output`. 3. `load_cache()` returns the cached profile. 4. The cached branch writes the profile using `Path.write_text()`. 5. The resulting file inherits permissions from the process umask rather than being ...[truncated 704 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `Path.write_text()` with the same secure writer used for fresh profiles: ```python fd = os.open( str(args.output), os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600, ) with os.fdopen(fd, "w") as output_file: output_file.write(output) ``` 2. Centralize profile output in one helper so cached and fresh paths cannot diverge. 3. If the destination already exists, explicitly apply mode `0600` after validating that it is a regular file and not an unsafe symlink. 4. Create parent directories with mode `0700` when the application creates them. 5. Add a regression test that exports a cached profile and verifies that the resulting file mode is `0600`. 6. Document that profile exports contain private listening-derived data and should not be placed in shared directories. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup_cron.py:91
Finding
Cron Log Files May Expose Listening and Playlist Data to Other Local Users<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup_cron.py:91-96` **Vulnerability Type**: Sensitive scheduled-job output written without explicit private permissions **Risk Level**: Medium ### Vulnerable Code ```python def format_cron_line(job: dict, name: str) -> str: """Format a single crontab line with logging and marker.""" return ( f"{job['schedule']} {job['command']} >> {job['log']} 2>&1 " f"{MARKER}:{name}" ) ``` The log directory is created without an explicit restrictive mode at lines 153-156: ```python def cmd_install(job_defs: dict[str, dict], selected: list[str], log_dir: str): """Install selected cron jobs.""" # Ensure log directory exists Path(log_dir).mkdir(parents=True, exist_ok=True) ``` ### Technical Analysis All scheduled-job standard output and standard error are appended to log files using shell redirection. The setup code creates the log directory with permissions determined by the process umask and does not pre-create log files with mode `0600`. The scheduled scripts can emit playlist names, track selections, artist preferences, recommendation rationales, playlist identifiers, health-check results, and operational error messages. Because shell redirection creates absent log files using ambient permissions, a typical umask may result in locally readable files. The risk also applies to custom `--log-dir` values. The implementation does not verify ownership, reject symlinks, or ensure that the selected directory is private. ### Attack Path 1. The user installs one or more scheduled jobs through `setup_cron.py`. 2. The setup process creates the log directory without enforcing mode `0700`. 3. Cron runs a configured recommendation, playlist, release, or health-check job. 4. Shell redirection creates or appends to the configured log file. 5. The file receives permissions based on cron's umask rather than an application-enforced private mode. 6. Another local use ...[truncated 816 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the default log directory with mode `0700` and verify its final permissions: ```python Path(log_dir).mkdir(parents=True, exist_ok=True, mode=0o700) os.chmod(log_dir, 0o700) ``` 2. Pre-create every log file using `os.open()` with mode `0600` before installing the cron entry. 3. Verify that the log directory and files are owned by the current user and are regular files rather than symlinks. 4. Reject newline and control characters in custom log paths. 5. Shell-quote the redirection path with `shlex.quote()` in addition to fixing the command-injection issue. 6. Minimize scheduled-job output and avoid logging full recommendation or playlist JSON unless explicitly requested. 7. Implement log rotation and a documented cleanup command to prevent indefinite retention. 8. Add tests that verify directory mode `0700`, file mode `0600`, safe handling of paths containing spaces, and rejection of symlinked destinations. ]]>
Vulnerability Patterns
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (75)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### Fixed — Security (15 issues)

- Tokens passed via `curl -K` config files instead of CLI arguments (prevents `ps aux` exposure)
- Token echo truncated to first 20 chars in verify_setup
- File permissions set to `0o600` for all generated files (cache, cards, config)
- `$TMPDIR` used for temporary files instead of predictable paths
Confidence
60% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
2. **Keep `.env` in `.gitignore`** — The repo ships with this configured
3. **Rotate tokens periodically** — Dev tokens support up to 6-month lifetime
4. **Review cache contents** — `~/.apple-music-dj/` contains your taste profile
5. **Clear cache when sharing machines** — `rm -rf ~/.apple-music-dj/`
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
2. **Keep `.env` in `.gitignore`** — The repo ships with this configured
3. **Rotate tokens periodically** — Dev tokens support up to 6-month lifetime
4. **Review cache contents** — `~/.apple-music-dj/` contains your taste profile
5. **Clear cache when sharing machines** — `rm -rf ~/.apple-music-dj/`
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
2. **Keep `.env` in `.gitignore`** — The repo ships with this configured
3. **Rotate tokens periodically** — Dev tokens support up to 6-month lifetime
4. **Review cache contents** — `~/.apple-music-dj/` contains your taste profile
5. **Clear cache when sharing machines** — `rm -rf ~/.apple-music-dj/`
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
2. **Keep `.env` in `.gitignore`** — The repo ships with this configured
3. **Rotate tokens periodically** — Dev tokens support up to 6-month lifetime
4. **Review cache contents** — `~/.apple-music-dj/` contains your taste profile
5. **Clear cache when sharing machines** — `rm -rf ~/.apple-music-dj/`
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
2. **Keep `.env` in `.gitignore`** — The repo ships with this configured
3. **Rotate tokens periodically** — Dev tokens support up to 6-month lifetime
4. **Review cache contents** — `~/.apple-music-dj/` contains your taste profile
5. **Clear cache when sharing machines** — `rm -rf ~/.apple-music-dj/`
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
2. **Keep `.env` in `.gitignore`** — The repo ships with this configured
3. **Rotate tokens periodically** — Dev tokens support up to 6-month lifetime
4. **Review cache contents** — `~/.apple-music-dj/` contains your taste profile
5. **Clear cache when sharing machines** — `rm -rf ~/.apple-music-dj/`
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
2. **Keep `.env` in `.gitignore`** — The repo ships with this configured
3. **Rotate tokens periodically** — Dev tokens support up to 6-month lifetime
4. **Review cache contents** — `~/.apple-music-dj/` contains your taste profile
5. **Clear cache when sharing machines** — `rm -rf ~/.apple-music-dj/`
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
2. **Keep `.env` in `.gitignore`** — The repo ships with this configured
3. **Rotate tokens periodically** — Dev tokens support up to 6-month lifetime
4. **Review cache contents** — `~/.apple-music-dj/` contains your taste profile
5. **Clear cache when sharing machines** — `rm -rf ~/.apple-music-dj/`
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding points to system-level cron/crontab management and log redirection under a skill marketed mainly as music personalization. Scheduled-task installation/modification increases risk because it persists behavior beyond a single user request and can execute repeatedly with the user's privileges if misconfigured or abused.

Static analysis

No suspicious patterns detected.