Most active commenters
  • tptacek(5)
  • otterley(4)
  • ollien(3)

←back to thread

786 points rexpository | 13 comments | | HN request time: 1.151s | source | bottom
Show context
tptacek ◴[] No.44503091[source]
This is just XSS mapped to LLMs. The problem, as is so often the case with admin apps (here "Cursor and the Supabase MCP" is an ad hoc admin app), is that they get a raw feed of untrusted user-generated content (they're internal scaffolding, after all).

In the classic admin app XSS, you file a support ticket with HTML and injected Javascript attributes. None of it renders in the customer-facing views, but the admin views are slapped together. An admin views the ticket (or even just a listing of all tickets) and now their session is owned up.

Here, just replace HTML with LLM instructions, the admin app with Cursor, the browser session with "access to the Supabase MCP".

replies(4): >>44503182 #>>44503194 #>>44503269 #>>44503304 #
1. otterley ◴[] No.44503269[source]
Oh, Jesus H. Christ: https://github.com/supabase-community/supabase-mcp/blob/main...
replies(2): >>44503322 #>>44503344 #
2. tptacek ◴[] No.44503322[source]
This to me is like going "Jesus H. Christ" at the prompt you get when you run the "sqlite3" command. It is also crazy to point that command at a production database and do random stuff with it. But not at all crazy to use it during development. I don't think this issue is as complicated, or as LLM-specific, as it seems; it's really just recapitulating security issues we understood pretty clearly back in 2010.

Actually, in my experience doing software security assessments on all kinds of random stuff, it's remarkable how often the "web security model" (by which I mean not so much "same origin" and all that stuff, but just the space of attacks and countermeasures) maps to other unrelated domains. We spent a lot of time working out that security model; it's probably our most advanced/sophisticated space of attack/defense research.

(That claim would make a lot of vuln researchers recoil, but reminds me of something Dan Bernstein once said on Usenet, about how mathematics is actually one of the easiest and most accessible sciences, but that ease allowed the state of the art to get pushed much further than other sciences. You might need to be in my head right now to see how this is all fitting together for me.)

replies(2): >>44503485 #>>44504552 #
3. noselasd ◴[] No.44503344[source]
It's an MCP for your database, ofcourse it's going to execute SQL. It's your responsibility for who/what can access the MCP that you've pointed at your database.
replies(2): >>44503594 #>>44504647 #
4. ollien ◴[] No.44503485[source]
> It is also crazy to point that command at a production database and do random stuff with it

In a REPL, the output is printed. In a LLM interface w/ MCP, the output is, for all intents and purposes, evaluated. These are pretty fundamentally different; you're not doing "random" stuff with a REPL, you're evaluating a command and _only_ printing the output. This would be like someone copying the output from their SQL query back into the prompt, which is of course a bad idea.

replies(1): >>44503532 #
5. tptacek ◴[] No.44503532{3}[source]
The output printing in a REPL is absolutely not a meaningful security boundary. Come on.
replies(1): >>44503602 #
6. otterley ◴[] No.44503594[source]
Except without any authentication and authorization layer. Remember, the S in MCP is for "security."

Also, you can totally have an MCP for a database that doesn't provide any SQL functionality. It might not be as flexible or useful, but you can still constrain it by design.

replies(1): >>44505023 #
7. ollien ◴[] No.44503602{4}[source]
I won't claim to be as well-versed as you are in security compliance -- in fact I will say I definitively am not. Why would you think that it isn't a meaningful difference here? I would never simply pipe sqlite3 output to `eval`, but that's effectively what the MCP tool output is doing.
replies(1): >>44503635 #
8. tptacek ◴[] No.44503635{5}[source]
If you give a competent attacker a single input line on your REPL, you are never again going to see an output line that they don't want you to see.
replies(1): >>44503668 #
9. ollien ◴[] No.44503668{6}[source]
We're agreeing, here. I'm in fact suggesting you _shouldn't_ use the output from your database as input.
10. otterley ◴[] No.44504552[source]
> This to me is like going "Jesus H. Christ" at the prompt you get when you run the "sqlite3" command.

Sqlite is a replacement for fopen(). Its security model is inherited from the filesystem itself; it doesn't have any authentication or authorization model to speak of. What we're talking about here though is Postgres, which does have those things.

Similarly, I wouldn't be going "Jesus H. Christ" if their MCP server ran `cat /path/to/foo.csv` (symlink attacks aside), but I would be if it run `cat /etc/shadow`.

11. minitech ◴[] No.44504647[source]
I think you missed the second, much more horrifying part of the code at the link. The thing “stopping” the output from being treated as instructions appears to be a set of instructions.

(permalink: https://github.com/supabase-community/supabase-mcp/blob/2ef1...)

12. tptacek ◴[] No.44505023{3}[source]
No part of what happened in this bug report has anything to do with authentication and authorization. These developers are using the MCP equivalent of a `psql` prompt. They assume full access.

I think this "S in MCP" stuff is a really handy indicator for when people have missed the underlying security issue, and substituted some superficial thing instead.

replies(1): >>44506488 #
13. otterley ◴[] No.44506488{4}[source]
What do you think the underlying security issue is? I see at least two of them.

Also, psql doesn’t automatically provide its caller with full access to a database server—or any access at all, for that matter. You still have to authenticate yourself somehow, even if you’re it’s just local peer authentication.

If this MCP server is running with your own credentials, and your credentials give you full access to the database, then the fact that the service can be used to make arbitrary queries to the database is not remarkable: It’s literally your agent. We’d call it a bug, not necessarily a security risk. However, if it’s running with credentials that aren’t yours that provide full access, and your own credentials don’t, then this bug becomes a privilege escalation attack vector. It’s a classic confused deputy problem.

The situation with MCP today reminds me of the 1990s when everyone ran open SMTP servers. It wasn’t a big deal at first, but once the abuse became bad enough, we had to do something about it. SMTP didn’t have any security facilities in it, so we had to experiment with patchy solutions and ended up with a in-band solution involving the AUTH extension and SASL.

Something similar is going on with MCP right now. It doesn’t offer an in-band generic authentication support (hence the missing “S”). There’s no way I’m aware of to pass arbitrary application credentials to an MCP server so it can act as a database query agent that can do only as much as your credentials permit. There seems to be limited support for bearer tokens and OAuth, but neither of those directly translate to database credentials.