T09 · Insecure Skill Coding Practices
- Location
scripts/odoo_mcp.py:48- Finding
Bearer credential can be transmitted to an untrusted or plaintext endpoint
- Content
View full analysis
Vulnerability Details
File Location:
scripts/odoo_mcp.py:48-69
Vulnerability Type: Missing endpoint and transport validation for sensitive credential transmission
Risk Level: HighVulnerable Code
python def _config(): url = (os.environ.get("ODOO_MCP_URL") or "").strip() token = (os.environ.get("ODOO_MCP_TOKEN") or "").strip() return url, token async def _with_session(url: str, headers: dict, fn): async with streamablehttp_client(url, headers=headers) as (read, write, _): async with ClientSession(read, write) as session: await session.initialize() return await fn(session) async def _run(fn) -> int: url, token = _config() if not url or not token: return _fail( "config_error", "Set ODOO_MCP_URL and ODOO_MCP_TOKEN before using this skill.", code=2, ) headers = {"Authorization": f"Bearer {token}"} try:The associated configuration documentation at
SKILL.md:16-24confirms that the URL is externally configurable and that the secret is sent as a Bearer token:yaml ODOO_MCP_URL: required: true description: > Full URL of the Odoo MCP endpoint, e.g. `https://odoo.example.com/drivethru_mcp/v1` (the MCP server exposed by the `drivethru_mcp` Odoo module, not the Odoo base URL). ODOO_MCP_TOKEN: required: true description: > The `drivethru.mcp_key` value from the Odoo `drivethru_mcp` module, sent as `Authorization: Bearer`. Treat as a secret; never paste into chat.Technical Analysis
The client accepts
ODOO_MCP_URLas an arbitrary string and sends the static Odoo MCP token to that URL in theAuthorizationheader. It does not independently enforce HTTPS, validate the expected hostname, reject embedded URL credentials, or restrict loopback, link-local, and other unexpected destinations.Sending a credential to the configured Odoo MCP endpoint is necessary for the Skill's declare ...[truncated 1937 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse the URL with a standard URL parser and reject malformed URLs.
- Require the
httpsscheme in production; permit HTTP only behind an explicit development-only option. - Reject URLs containing embedded usernames or passwords.
- Enforce an administrator-controlled hostname allowlist or bind the expected endpoint host separately from user-controlled task input.
- Resolve and reject loopback, link-local, multicast, and private destinations unless an administrator explicitly permits the required internal Odoo host.
- Ensure redirects cannot forward the
Authorizationheader to a different origin. - Use normal TLS certificate verification and provide certificate or public-key pinning where the deployment model supports it.
- Replace broadly privileged static credentials with narrowly scoped, revocable, and regularly rotated tokens.
- Restrict who can modify the Skill's environment and endpoint configuration.
- Add tests confirming rejection of
http://, embedded credentials, unexpected hosts, and unsafe redirect destinations.
