MCP OAuth Redirect Handler Command Injection (sequa-mcp redirectToAuthorization)
An MCP client library builds a command to open a browser for OAuth login, but inserts the authorization URL into that command without checking it first. If the URL comes from a malicious or compromised OAuth server, an attacker can hide shell commands inside it that run when the client tries to open the login page.
How the attack works
An MCP client (affected: sequa-ai sequa-mcp version 1.0.13 and earlier, in redirectToAuthorization; the same flaw can exist in other MCP clients with the same pattern) fetches OAuth discovery/authorization details from a server and builds a command line to launch a URL opener such as xdg-open, open, start, rundll32 url.dll, a browser binary, or python -m webbrowser. If the discovery URL or its parameters are not validated, an attacker-controlled OAuth server can return a URL containing shell metacharacters or command substitution alongside the real link. When the client spawns the opener, the shell also executes the injected command — for example a curl, wget, netcat, /bin/sh, python -c, or powershell invocation — giving the attacker code execution on the machine running the MCP client, all triggered by what looks like a normal login step.
Netzilo detection
Netzilo reports this behaviour when it is observed.
- Signature ID
- 7c1e4b2a-9f3d-4e58-b0a6-2d51c9f4e83b
- Severity
- High
Why it matters
An attacker who controls or spoofs an OAuth discovery endpoint can get arbitrary command execution on the developer or service machine that runs the MCP client, without any further interaction beyond the normal OAuth login flow.
What you can do
- →Upgrade sequa-mcp past 1.0.13 or patch any custom redirectToAuthorization / browser-launch code to validate and sanitize the discovery and authorization URLs before using them.
- →Never pass a URL fetched from an external OAuth server directly into a shell command; use APIs that spawn the opener with argument arrays instead of a shell string.
- →Restrict which OAuth issuers/discovery endpoints your MCP clients are allowed to trust, and pin or allowlist known-good authorization servers.
- →Review logs for URL-opener commands that mix an http(s) OAuth URL with shell separators or command substitution pointing at curl, wget, nc, /bin/sh, python -c, or powershell.
Known benign look-alikes
- Developer or CI shell wrappers that build an OAuth authorization URL with command substitution before launching a browser, e.g. 'xdg-open "https://idp/authorize?client_id=$(cat id)&code_challenge=$(gen)"'. Mitigated by restricting substitution bodies to remote-fetch / shell-exec verbs (curl, wget, nc, /bin/sh, python -c, powershell -, mkfifo, certutil) rather than value-producing helpers such as cat, hostname, whoami, openssl or base64.
- End-to-end OAuth login tests (Playwright, Cypress, Selenium) that spawn a browser with a crafted authorization URL containing separators inside query values. Mitigated by filter_test_scanners.
- Security research, CVE reproduction scripts and vulnerability-scanner rule content that embeds this exact command shape. Mitigated by filter_placeholder_docs and the scanner names in filter_test_scanners.
- grep/rg/sed/man over source or logs containing the vulnerable one-liner (code review, incident triage). Mitigated by filter_text_tools.
- Legitimate authorization URLs whose query values contain a single '&' or ';' separator; the rule requires ';', '&&', '||' or '|' followed by an actual executable verb, so ordinary '&'-delimited OAuth parameters never match.