Back to skill

Security audit

Beatport Download via Browser Tool

Security checks for vulnerabilities and agentic risk

Overview

This Beatport downloader has a coherent purpose, but it uses overbroad browser-session access and under-scoped file and credential handling that should be reviewed before installation.

Install only if you are comfortable giving the skill access to an authenticated Beatport browser session and local download directories. Use a dedicated temporary Chrome profile for Beatport, avoid reusing a browser profile with other logged-in sites, do not paste cookies into shell history or logs, and review any file cleanup commands before running them.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/beatport-cdp.js:166
Finding
Browser-Wide Cookie Disclosure Through CDP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/beatport-cdp.js`, lines 166-180 **Vulnerability Type**: Excessive browser-session access **Risk Level**: High ### Vulnerable Code ```javascript /** * Get all cookies for a domain */ function getCookies(ws, urls) { return new Promise((resolve, reject) => { const id = Date.now(); const handler = (m) => { const d = JSON.parse(m.toString()); if (d.id === id) { ws.removeListener("message", handler); resolve(d.result.cookies); } }; ws.on("message", handler); ws.send(JSON.stringify({ id, method: "Network.getAllCookies", params: urls ? { urls } : {} })); }); } ``` ### Technical Analysis The exported helper invokes `Network.getAllCookies`, which retrieves cookies available to the attached browser profile rather than limiting retrieval to the Beatport authentication cookies required by the Skill. The function can also be called without a URL argument. Passing `urls` in the request does not provide a reliable security boundary for `Network.getAllCookies`. Consequently, if the CDP instance uses a shared browser profile, the result may include authentication cookies for unrelated websites open in that profile. This exceeds minimum privilege because the declared functionality only requires Beatport cookies or operation within an already authenticated Beatport page. ### Attack Path 1. A caller loads `scripts/beatport-cdp.js`. 2. The caller discovers or selects a page attached to the local CDP endpoint. 3. The caller establishes a WebSocket connection using `connectPage`. 4. The caller invokes `getCookies(ws)` without a restrictive argument. 5. Chrome returns cookies from the attached browser profile. 6. The caller extracts unrelated session tokens and attempts to replay them against their corresponding services. ### Impact Assessment A malicious or compromised workflow could disclose session cookies belonging to unrelated w ...[truncated 345 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Run the automation in a dedicated, ephemeral Chrome profile used only for Beatport. - Replace `Network.getAllCookies` with `Network.getCookies` for an explicit allowlist such as: - `https://www.beatport.com/` - `https://account.beatport.com/` - Reject returned cookies whose domains are not exactly approved Beatport domains or valid subdomains. - Do not export a general-purpose cookie enumeration function unless it is essential. - Keep cookies in memory only for the shortest required duration. - Never print, persist, or return complete cookie collections to an untrusted caller. - Require the CDP endpoint to remain bound to loopback and prevent access by untrusted local processes where possible. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/beatport-cdp.js:76
Finding
Browser-Context JavaScript Injection Through Unsafely Interpolated Inputs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/beatport-cdp.js`, lines 76-89 and 188-216 **Vulnerability Type**: JavaScript injection into CDP `Runtime.evaluate` expressions **Risk Level**: High ### Vulnerable Code Navigation input is directly inserted into JavaScript source: ```javascript /** * Navigate to a URL (using location.href for cross-domain support) */ function navigate(ws, url) { return new Promise((resolve, reject) => { const id = Date.now(); const handler = (m) => { const d = JSON.parse(m.toString()); if (d.id === id) { ws.removeListener("message", handler); resolve(); } }; ws.on("message", handler); ws.send(JSON.stringify({ id, method: "Runtime.evaluate", params: { expression: `location.href = "${url}"` } })); }); } ``` Credentials are also directly inserted into executable expressions: ```javascript await evalJs(ws, ` var userInput = document.querySelector("input[name=username]") || document.querySelector("input[id=id_username]"); if (userInput) { var nativeSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value").set; nativeSetter.call(userInput, "${username}"); userInput.dispatchEvent(new Event("input", { bubbles: true })); userInput.dispatchEvent(new Event("change", { bubbles: true })); } `); await evalJs(ws, ` var passInput = document.querySelector("input[name=password]") || document.querySelector("input[id=id_password]"); if (passInput) { var nativeSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value").set; nativeSetter.call(passInput, "${password}"); passInput.dispatchEvent(new Event("input", { bubbles: true })); passInput.dispatchEvent(new Event("change", { bubbles: true })); } `); ``` ### Technical Analysis The `url`, `username`, and `password` values are embedded inside quoted JavaScript string literals without e ...[truncated 1852 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never concatenate untrusted values into source code passed to `Runtime.evaluate`. - At minimum, serialize values using `JSON.stringify`: ```javascript const safeUrl = JSON.stringify(url); params: { expression: `location.href = ${safeUrl}` } ``` - Apply the same serialization to usernames and passwords. - Prefer CDP mechanisms that pass values as call arguments, such as obtaining a function object and invoking it through `Runtime.callFunctionOn`. - Parse navigation input with `new URL(url)` and enforce all of the following: - Protocol must be `https:`. - Hostname must match an explicit Beatport allowlist. - Embedded usernames and passwords must be rejected. - Keep authentication inputs in memory only and ensure they are never logged. - Add tests using quotes, backslashes, newlines, and JavaScript-like payloads to verify that inputs remain inert data. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:135
Finding
Authentication Cookies Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 135-138 and 143-146 **Vulnerability Type**: Sensitive session data exposed in process arguments **Risk Level**: Medium ### Vulnerable Code ```bash curl -s -H "Cookie: <cookies>" \ "https://www.beatport.com/_next/data/<buildId>/en/library/downloads.json" \ | jq -r '.pageProps.accessToken' ``` ```bash curl -s -H "Cookie: <cookies>" \ "https://www.beatport.com/_next/data/<buildId>/en/library.json" \ | jq '.pageProps.dehydratedState.queries[].state.data.results[] | {name, id, artists}' ``` ### Technical Analysis The documentation instructs the operator or agent to place complete authentication cookies in a `curl` command-line argument. Command-line arguments can be exposed through process inspection facilities, shell history, terminal capture, automation logs, diagnostic telemetry, or wrapper-tool logging. The requests are directed to the legitimate Beatport HTTPS domain, so transmitting the cookie to Beatport is necessary for authenticated API access. The weakness is the local secret-handling method, not the intended HTTPS destination. ### Attack Path 1. The user or agent retrieves authenticated Beatport cookies. 2. It substitutes those cookies into the documented `curl -H` command. 3. The full cookie header appears in the process argument list or execution logs. 4. Another local process, user, monitoring service, or retained log captures the cookie. 5. The exposed session cookie is replayed against Beatport before it expires or is revoked. ### Impact Assessment A leaked Beatport session cookie could permit unauthorized access to library metadata, download-related endpoints, and other actions allowed by the authenticated session. The precise impact depends on Beatport's session validation, expiration, and anti-replay controls. This does not expose unrelated browser sessions by itself, but it can compromise the user's Beatport account session. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Do not place authentication cookies directly in shell command arguments. - Prefer an in-process HTTPS client that accepts headers as data and does not expose them in the process list. - If `curl` must be used, load sensitive configuration from a permission-restricted temporary configuration file rather than directly from the command line. - Create temporary secret files with permissions restricted to the current user and remove them immediately after use. - Disable command tracing while secrets are handled. - Redact `Cookie`, `Authorization`, access-token, and download-token values from logs. - Avoid saving commands containing secrets in shell history. - Revoke the Beatport session immediately if cookie exposure is suspected. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/beatport-cdp.js:126
Finding
Unrestricted Download Paths and Unsafe Archive Cleanup<![CDATA[ ## Vulnerability Details **File Location**: `scripts/beatport-cdp.js`, lines 126-155; `SKILL.md`, lines 115-120 **Vulnerability Type**: Unsafe filesystem path and temporary-file handling **Risk Level**: Medium ### Vulnerable Code The helper accepts a download path without validation: ```javascript /** * Enable downloads to a specific directory (browser-level) */ async function enableDownloads(downloadPath) { const browserWsUrl = await getBrowserWs(); return new Promise((resolve, reject) => { const ws = new WS(browserWsUrl); ws.on("open", () => { ws.send(JSON.stringify({ id: 1, method: "Browser.setDownloadBehavior", params: { behavior: "allowAndName", downloadPath: downloadPath, eventsEnabled: true } })); }); ws.on("message", (m) => { const d = JSON.parse(m.toString()); if (d.id === 1) { ws.close(); resolve(d.result); } }); ws.on("error", reject); }); } ``` The documentation recommends extraction and broad cleanup in a fixed directory: ```bash cd /path/to/download/dir unzip -o beatport_tracks_*.zip -d tmp/ mv tmp/*.mp3 . rm -rf tmp/ beatport_tracks_*.zip ``` ### Technical Analysis `enableDownloads` forwards an arbitrary caller-provided filesystem path to the browser without resolving it against a dedicated download root or checking whether the destination is appropriate. The documented shell workflow uses a predictable directory named `tmp`, overwrites extracted files with `unzip -o`, moves all matching MP3 files, recursively deletes `tmp`, and deletes every archive matching `beatport_tracks_*.zip`. It does not verify whether these paths and files were created by the current operation. The extraction instructions also do not inspect archive entries for absolute paths or parent-directory traversal before extraction. Beatport is the expected archive source, which reduces ordinary exposure, but validating arc ...[truncated 1387 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Define a dedicated download root owned by the current user. - Resolve the requested path with `realpath` or `path.resolve` and verify that it remains beneath the approved root. - Reject root directories, home directories, symbolic-link escapes, and paths outside the approved download area. - Create a unique private working directory for each operation, for example with `mktemp -d`. - Record every file created by the current run and delete only those recorded files. - Do not use broad cleanup patterns such as: ```bash rm -rf tmp/ beatport_tracks_*.zip ``` - List and validate archive entries before extraction. - Reject absolute paths, `..` components, device paths, and symbolic-link entries that escape the extraction root. - Extract into a newly created empty directory and move only validated audio files. - Avoid unconditional overwrite options unless the destination has been verified to contain only current-run files. - Use cleanup handlers that delete the unique working directory after confirming it is inside the approved root. ]]>
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (8)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
cd /path/to/download/dir
unzip -o beatport_tracks_*.zip -d tmp/
mv tmp/*.mp3 .
rm -rf tmp/ beatport_tracks_*.zip
```

### Download URL Format
Confidence
94% confidence
Finding
The documented use of shell cleanup with 'rm -rf' introduces destructive filesystem behavior into the skill. In an agentic environment, variable path expansion, working-directory confusion, or malformed globbing can delete unintended files beyond the downloaded archive contents.

Credential Access

High
Category
Privilege Escalation
Content
## API Access

### Access Token

```bash
curl -s -H "Cookie: <cookies>" \
Confidence
95% confidence
Finding
The skill includes guidance for extracting an access token from authenticated Beatport responses using session cookies. Even if intended for legitimate use, exposing token-harvesting steps within an agent skill materially increases the risk of credential/session misuse, replay, and unauthorized API access if logs, prompts, or tool outputs are exposed.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger phrases are broad enough to match generic requests like 'download my tracks' that may not clearly refer to Beatport. This can cause the skill to activate in the wrong context, leading to unintended login handling, browser automation, or file downloads against the wrong user intent.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill’s stated purpose is downloading already purchased tracks, but it also documents cart, checkout, and payment-related URLs. Expanding the workflow into purchase flows increases the chance the agent navigates into transactional areas and performs unintended commerce actions, especially in an automated browser context with authenticated sessions.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill instructs unzipping, moving, and deleting files locally without any warning, confirmation, or path-safety constraints. In an automation setting, file modification and deletion can destroy user data or overwrite files if paths or glob patterns are broader than expected.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The getCookies function retrieves all browser cookies via the DevTools protocol, which can expose authenticated session tokens well beyond Beatport-specific needs. Within a browser automation skill, undisclosed cookie access is especially dangerous because it enables session hijacking or cross-site account compromise if those cookies are exfiltrated or misused.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This code automates credential entry and submission into Beatport's login form without any explicit user consent, disclosure, or guardrails around how credentials are sourced and used. In the context of an agent skill, this increases the risk of covert credential collection, replay, or accidental use of sensitive account data beyond the user's clear expectations.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The screenshot function captures whatever is visible in the browser and writes it directly to disk, potentially storing account details, purchase history, or other sensitive page content without notice. Although screenshots can be legitimate for debugging, silent persistence of page data creates unnecessary privacy and data-retention risk in an automation skill handling authenticated sessions.

Static analysis

No suspicious patterns detected.