Back to skill

Security audit

Freesound API

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says for Freesound API use, but its credential handling is risky enough that users should review it before installing.

Install only if you are comfortable storing Freesound API credentials locally in plaintext. Prefer rotating any secret already entered on the command line, restrict the credential file to your user account, avoid shared machines, and review the scripts before using downloads with authenticated tokens.

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

Warning
Location
scripts/freesound_config.py:23
Finding
OAuth Tokens and Client Secrets Stored Without Explicit Access Controls<![CDATA[ ## Vulnerability Details **File Location**: `scripts/freesound_config.py`, lines 23–26 **Vulnerability Type**: Plaintext credential storage with inherited file permissions **Risk Level**: Medium ### Vulnerable Code ```python def save_config(data: dict) -> None: ensure_app_dir() CONFIG_PATH.write_text(json.dumps(data, indent=2), encoding="utf-8") ``` ### Technical Analysis The configuration object contains the Freesound client secret and, after OAuth authentication, access-token data. `save_config()` serializes this sensitive data into a plaintext JSON file. The file is created without explicitly enforcing owner-only permissions or validating the inherited directory ACL. Its effective access controls therefore depend on the operating system, current process umask, and inherited permissions on the parent directory. On a shared or incorrectly configured system, another local account or process may be able to read the credentials. The local storage is necessary for the declared functionality, but storing reusable secrets in plaintext without enforcing restrictive access controls exceeds the minimum safe privilege model. ### Attack Path 1. The user runs `setup_credentials.py` or `oauth_login.py`. 2. `save_config()` writes the client secret and OAuth token to `credentials.json`. 3. The file inherits permissive filesystem permissions or ACL entries. 4. A local attacker or compromised process reads the JSON file. 5. The attacker extracts the OAuth access token, refresh token if returned, or Freesound client secret. 6. The stolen credential is reused to make authenticated Freesound API requests. ### Impact Assessment Successful exploitation can expose all credentials stored in the configuration file. An attacker may obtain the same Freesound API access granted to the authenticated user, subject to the token's scope and server-side permissions. This issue does not directly provide operating-system privilege escalation. Its scope is credential ...[truncated 94 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Prefer an operating-system credential manager, such as Windows Credential Manager, rather than a plaintext JSON file. - If file storage is required, create the directory and file with owner-only access. - On POSIX systems, use mode `0700` for the directory and `0600` for the credential file. - On Windows, apply and verify an ACL that grants access only to the current user and required system principals. - Write credentials atomically through a securely created temporary file, apply restrictive permissions, and then replace the destination file. - Validate existing permissions during every load and refuse to use a credential file that is accessible to unintended users. - Store only credentials required for current operation and provide a secure command to delete or revoke stored tokens. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/download_sound.py:58
Finding
Authentication Credentials May Be Forwarded to an Unvalidated Download Host<![CDATA[ ## Vulnerability Details **File Location**: `scripts/download_sound.py`, lines 58–70 **Vulnerability Type**: Credential disclosure through an unvalidated API-provided URL **Risk Level**: Medium ### Vulnerable Code ```python if args.preview: key = f"preview-{args.preview}" download_url = (info.get("previews") or {}).get(key) if not download_url: raise SystemExit(f"Preview URL not available for {key}.") else: download_url = info.get("download") if not download_url: raise SystemExit("No download URL returned for this sound.") headers, params = get_auth_headers_and_params() response = requests.get(download_url, headers=headers, params=params, stream=True, timeout=60) ``` ### Technical Analysis The download URL is taken directly from the Freesound API response. Before making the request, the code obtains either: - An OAuth bearer token, which is placed in the `Authorization` header; or - The saved client secret/API key, which is placed in the `token` query parameter. The URL's scheme and hostname are not validated before these credentials are attached. If the API response is manipulated, the service is compromised, or an unexpected external preview URL is returned, the script can transmit credentials to a host outside the intended Freesound trust boundary. The risk also applies to redirects because `requests.get()` follows redirects by default. A trusted initial endpoint could redirect to another origin while retaining sensitive query data in some request flows. Authentication should be attached only to explicitly trusted endpoints and only when required. ### Attack Path 1. An attacker compromises or manipulates the API response, or causes it to contain an attacker-controlled `download` or `previews` URL. 2. The user invokes `download_sound.py` for the affected sound. 3. The script selects the untrusted URL without validating its origin. 4. `get_auth_headers_and_params ...[truncated 687 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse `download_url` and require HTTPS. - Maintain an explicit allowlist of trusted Freesound download and preview hostnames. - Reject URLs containing user information, unusual ports, or hosts outside the allowlist. - Do not attach credentials to public preview URLs when authentication is unnecessary. - Disable automatic redirects for authenticated downloads, or validate every redirect target before following it. - Strip the `Authorization` header and secret-bearing query parameters whenever a redirect crosses origins. - Prefer constructing authenticated API download endpoints from trusted constants rather than consuming arbitrary absolute URLs from API data. - Never place a client secret in a query string when a safer supported authentication mechanism is available. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup_credentials.py:7
Finding
Client Secret Accepted Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup_credentials.py`, lines 7–8 **Vulnerability Type**: Sensitive credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument("--client-id", required=True) parser.add_argument("--client-secret", required=True) ``` The documented invocation also instructs users to place the secret directly on the command line: ```powershell python scripts\setup_credentials.py --client-id '<CLIENT_ID>' --client-secret '<CLIENT_SECRET>' --redirect-uri 'http://localhost:8787/callback' ``` ### Technical Analysis The setup utility requires the client secret to be passed as a command-line argument. Command-line arguments can be retained in shell history, terminal logs, process-monitoring records, debugging output, or endpoint-management telemetry. Depending on operating-system controls, other local processes may also be able to inspect active process arguments. Although the client secret must be supplied during setup, exposing it through the command line is not necessary. It can instead be collected through a non-echoing interactive prompt or an operating-system credential manager. ### Attack Path 1. The user follows the documented command and supplies the real Freesound client secret through `--client-secret`. 2. The command is recorded in shell history, terminal logging, process telemetry, or another local monitoring source. 3. A local attacker or unauthorized operator reads the recorded command or inspects the process while it runs. 4. The attacker extracts the client secret. 5. The secret is reused to impersonate or abuse the associated Freesound API application, subject to the service's authentication requirements. ### Impact Assessment Exploitation discloses the Freesound application client secret. This may enable unauthorized API use or facilitate attacks against OAuth flows associated with the application. The issue doe ...[truncated 143 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the required `--client-secret` command-line option as the default secret-entry mechanism. - Read the secret interactively with Python's `getpass.getpass()` so it is not echoed. - Support retrieving the secret directly from an operating-system credential manager. - If automation is required, accept a protected file descriptor or a restricted-permission secret file and delete it securely after use. - Avoid documenting commands that contain literal secrets. - Warn users to remove any historical commands containing secrets and rotate a secret if it has already been exposed. - Do not print, log, or include the supplied secret in exception messages. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The declared description emphasizes setting up Freesound API access, OAuth localhost login, local credential storage, app registration/use, search helpers, and general data fetching. The supplied code chunk does not implement OAuth setup, credential storage, localhost login flow, or sound search. Instead, its concrete purpose is a downloader: it fetches metadata for a specific sound ID, chooses a preview or full download URL, authenticates the request, streams the audio content, and writes the file to disk. While downloading Freesound data is loosely related to 'fetch Freesound data,' the primary behavior here is specific file download and local saving, which is not clearly represented in the declared purpose and is materially different from the setup/auth/search focus.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description presents a broader skill centered on Freesound API setup and authenticated use, especially OAuth localhost login and local secret storage. The actual code chunk only implements a search helper over the Freesound search API and formats results. While sound search is one part of the declared description, the chunk does not reflect the main setup/auth/storage capabilities emphasized in the declared purpose. This is a material description-behavior mismatch for the supplied code chunk.

Credential Access

High
Category
Privilege Escalation
Content
This skill stores credentials in:

- `%APPDATA%\OpenClaw\freesound-api\credentials.json`

Keep the secret there, not in `SKILL.md`.
Confidence
88% confidence
Finding
The skill explicitly stores a client secret and later access tokens in a local JSON file under %APPDATA%. Plain local credential storage increases the risk of secret theft by other local users, malware, backups, logs, or accidental disclosure, especially because both long-lived app secrets and bearer tokens may reside together.

Credential Access

High
Category
Privilege Escalation
Content
1. Starts a temporary localhost callback server on port `8787`
2. Opens the Freesound authorization page in the browser
3. Receives the authorization code at `http://localhost:8787/callback`
4. Exchanges it for an access token
5. Saves the token back into `%APPDATA%\OpenClaw\freesound-api\credentials.json`

If the browser does not open, copy the printed URL manually.
Confidence
87% confidence
Finding
Handling and storing an OAuth access token is sensitive because bearer tokens grant direct API access without additional proof of possession. In this skill's context, the localhost OAuth callback and local token persistence make the token available to local compromise scenarios, which is especially relevant on shared or malware-exposed systems.

Credential Access

High
Category
Privilege Escalation
Content
2. Opens the Freesound authorization page in the browser
3. Receives the authorization code at `http://localhost:8787/callback`
4. Exchanges it for an access token
5. Saves the token back into `%APPDATA%\OpenClaw\freesound-api\credentials.json`

If the browser does not open, copy the printed URL manually.
Confidence
91% confidence
Finding
Persisting the OAuth access token back into the same local credentials.json file creates a reusable bearer-token theft risk. Anyone or any process that can read that file can impersonate the user against the Freesound API until the token expires or is revoked.

Credential Access

High
Category
Privilege Escalation
Content
from pathlib import Path

APP_DIR = Path(os.environ.get("APPDATA", Path.home() / ".config")) / "OpenClaw" / "freesound-api"
CONFIG_PATH = APP_DIR / "credentials.json"
DEFAULT_REDIRECT_URI = "http://localhost:8787/callback"
API_BASE = "https://freesound.org/apiv2"
AUTHORIZE_URL = f"{API_BASE}/oauth2/authorize/"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from pathlib import Path

APP_DIR = Path(os.environ.get("APPDATA", Path.home() / ".config")) / "OpenClaw" / "freesound-api"
CONFIG_PATH = APP_DIR / "credentials.json"
DEFAULT_REDIRECT_URI = "http://localhost:8787/callback"
API_BASE = "https://freesound.org/apiv2"
AUTHORIZE_URL = f"{API_BASE}/oauth2/authorize/"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill instructs use of capabilities equivalent to file read/write, local environment access, and network/OAuth flows, but it does not declare any explicit tool scope or permission boundaries. That makes the skill harder to sandbox or review and can permit broader-than-expected access to local credentials and network resources during execution.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The code falls back to using the stored client secret as a request token when no OAuth access token is present. A client secret is not intended to authenticate API data requests from a local helper this way, and repurposing it broadens secret exposure and can cause the secret to be sent to the remote service during routine API calls. In this skill context, that is more dangerous because the skill explicitly stores local credentials and automates API access, increasing the chance of accidental misuse or leakage of a long-lived secret.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
When no access token is present, the code places the credential into the URL query string via the 'token' parameter. Query parameters are commonly logged by clients, proxies, browser history, debugging tools, and server infrastructure, so transmitting a secret this way increases the chance of credential disclosure beyond normal header-based handling. Because this skill is designed for local setup and repeated API use, users may unknowingly leak a long-lived secret through logs or telemetry.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The code persists credential configuration to a predictable local file path without any protection, permission hardening, encryption, or user disclosure. In the context of this skill, the stored data is likely to include a Freesound client secret and possibly OAuth-related material, so compromise of the local user profile or accidental backup/sync exposure could leak secrets.

Missing User Warnings

Low
Confidence
87% confidence
Finding
The script performs a network download and writes the retrieved content to disk, creating the output directory if needed, but there is no confirmation prompt or user-facing warning before these actions. While downloading a sound is the stated purpose of the script, the code does not disclose that it will create directories and save files locally until after completion.

Static analysis

No suspicious patterns detected.