T09 · Insecure Skill Coding Practices
- Location
scripts/odds_api.py:112- Finding
API Key Disclosure Through Dry-Run Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a legitimate Odds-API.io helper, but it can expose the user's API key through dry-run output and through an unrestricted custom API endpoint option.
Install only if you are comfortable reviewing or hardening the helper first. Avoid using --dry-run with a real key, avoid --base-url entirely unless it is a trusted test endpoint with a non-production key, and prefer running it in an environment where ODDS_API_KEY is not broadly exposed.
scripts/odds_api.py:112API Key Disclosure Through Dry-Run Output
scripts/odds_api.py:253Unrestricted Base URL Allows API Key Exfiltration to Arbitrary Hosts
The skill describes use of environment variables and outbound network access via a CLI helper, but the manifest does not declare any explicit tool scope such as permissions or allowed-tools. This creates a least-privilege gap: an agent/runtime may permit broader capabilities than intended, making secret access and external exfiltration harder to govern or review.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import urllib.parse
import urllib.request
DEFAULT_BASE_URL = "https://api.odds-api.io/v3"
def build_url(base_url, path, params):
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import urllib.parse
import urllib.request
DEFAULT_BASE_URL = "https://api.odds-api.io/v3"
def build_url(base_url, path, params):
In the events command, dry-run prints the fully constructed URL, and this URL includes the apiKey query parameter. That exposes the secret to terminal history, logs, screenshots, and any calling framework that captures stdout. In an agent skill context, dry-run output may be surfaced back to users or observability systems, increasing the chance of credential leakage.
This is the same underlying issue as the SDI-2 finding at the events command: the code prints a credential-bearing query string during dry-run. Query-string secrets are particularly prone to disclosure through logs and copied output, so this is a genuine vulnerability rather than a false positive.
In the search command, dry-run outputs a URL containing the apiKey in the query string. Even without making the network call, this leaks the credential locally and to any system that records command output. Because this skill is designed for user-supplied API keys, protecting that value is especially important.
This search-path finding is valid because the dry-run path displays a URL whose query string contains the API key. Exposing secrets in query strings is dangerous in CLI and agent environments because output is often retained by shells, wrappers, and telemetry systems.
In the odds command, dry-run reveals the complete request URL including the apiKey. Secrets embedded in printed URLs are commonly captured by logs, chat transcripts, and monitoring tools, allowing reuse of the key by unauthorized parties. The betting-odds context does not reduce the sensitivity of the API credential.
This odds-path finding is also a true positive: a secret is embedded in a query string and then printed. That can lead to credential compromise if an attacker gains access to logs, terminal history, or captured agent output.
In the matchup command, dry-run prints the search URL containing the apiKey query parameter. This is a real secret-disclosure issue because dry-run is often used for debugging, where stdout is more likely to be copied into tickets, logs, or interactive agent responses. The skill context makes this more dangerous because agent tooling may automatically expose or retain command output.
This matchup dry-run branch prints a full search URL containing the API key in the query string. In practice, this can leak credentials through debug sessions and automated output collection, making it a real information disclosure issue.
No suspicious patterns detected.