T09 · Insecure Skill Coding Practices
- Location
scripts/robinhood_mcp.py:276- Finding
Stored Trading Credentials Are Not Bound to a Trusted Server Origin
- Content
View full analysis
str: return os.environ.get("ROBINHOOD_MCP_URL", DEFAULT_SERVER_URL) ``` ### Technical Analysis The OAuth provider loads credentials from the same `credentials.json` file regardless of the configured MCP server origin. At the same time, `ROBINHOOD_MCP_URL` can replace the trusted default endpoint with an arbitrary URL. OAuth access and refresh tokens are security-sensitive bearer credentials and must be bound to their intended resource server and authorization context. Reusing a common credential store after changing the endpoint can cause the authenticated client to present an existing token during communication with a substituted server. The implementation neither restricts custom endpoints to trusted Robinhood origins nor associates persisted credentials with the normalized server origin for which they were issued. The custom endpoint feature is not required for ordinary Robinhood trading functionality and therefore expands the trust boundary beyond the minimum privilege necessary for the declared functionality. ### Attack Path 1. A local attacker, compromised launcher, or unsafe deployment configuration sets `ROBINHOOD_MCP_URL` to an attacker-controlled endpoint. 2. The victim has previously authenticated, leaving valid Robinhood access and refresh tokens in `credentials.json`. 3. The victim or agent runs `status`, `tools`, or `call`. 4. `build_provider()` loads the shared credential store while using the attacker-controlled URL as the OAuth/MCP server URL. 5. Authentication or MCP tr ...[truncated 664 chars]- Remediation
View remediation
