T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/alpaca_api.py:52
- Finding
- Arbitrary Base URL Allows Alpaca Credential Exfiltration## Vulnerability Details **File Location**: `scripts/alpaca_api.py`, lines 52-84 **Vulnerability Type**: Unrestricted credential destination and insufficient URL validation **Risk Level**: High ### Vulnerable Code ```python base_url = os.getenv("ALPACA_BASE_URL", "https://paper-api.alpaca.markets") api_key = os.getenv("ALPACA_API_KEY") api_secret = os.getenv("ALPACA_API_SECRET") if not api_key or not api_secret: print("Error: Set ALPACA_API_KEY and ALPACA_API_SECRET environment variables", file=sys.stderr) sys.exit(1) if not endpoint.startswith("/"): print("Error: endpoint must start with '/' (example: /v2/account)", file=sys.stderr) sys.exit(2) url = f"{base_url}{endpoint}" headers = { "APCA-API-KEY-ID": api_key, "APCA-API-SECRET-KEY": api_secret, "Content-Type": "application/json", } allowed_methods = {"GET", "POST", "PUT", "PATCH", "DELETE"} method = method.upper() if method not in allowed_methods: print(f"Unsupported method: {method}. Supported: {', '.join(sorted(allowed_methods))}", file=sys.stderr) sys.exit(2) try: response = requests.request( method=method, url=url, headers=headers, params=params, json=data, timeout=timeout, ) ``` ### Technical Analysis `ALPACA_BASE_URL` is accepted without validating its scheme, hostname, port, path, user-information component, query, or fragment. The only related check verifies that the endpoint begins with `/`, which does not constrain the destination host. The helper then attaches both sensitive Alpaca authentication headers to the resulting URL. Consequently, anyone able to influence the process environment can redirect credentials to an arbitrary server. Plain HTTP destinations are also accepted, allowing credentials to be exposed through network interception. The `requests` library follows redirects by default. Because these credentials ...[truncated 2042 chars]
- Remediation
- ## Remediation Suggestions 1. Replace the arbitrary base URL with an explicit environment selector such as `ALPACA_ENVIRONMENT=paper|live`. 2. Map that selector internally to exact trusted origins: - `https://paper-api.alpaca.markets` - `https://api.alpaca.markets` - `https://data.alpaca.markets` only for operations that require the market-data API. 3. If custom base URLs are operationally necessary, parse them with `urllib.parse.urlsplit()` and require: - The `https` scheme. - A hostname from an explicit allowlist. - No username or password component. - No unexpected port. - No query or fragment. - An empty or explicitly permitted base path. 4. Set `allow_redirects=False` for authenticated requests. If redirects must be supported, validate each destination against the same trusted-origin allowlist before retransmitting credentials. 5. Use separate request clients or credential scopes for trading and market-data services so credentials are sent only where required. 6. Fail closed with a clear error when the configured destination is not trusted. 7. Add automated tests covering attacker-controlled hosts, plain HTTP URLs, user-information URLs, unexpected ports, malformed URLs, and redirects to untrusted origins. 8. Continue defaulting to paper trading, but do not treat documentation warnings as a substitute for runtime destination enforcement.
