👀 Our most exciting product launch yet 🚀 Join us May 8th for Sanity Connect

GROQ queries and security in Sanity.io

5 replies
Last updated: Feb 7, 2024
Is there a place I can read about GROQ queries and security?I stumbled upon queries like
*[_type == "page" && slug.current in ${slugs}]
and given that in that case slugs come from the URL I assume there's an GROQ injection risk there?Can't find much material on the topic.
Feb 4, 2024, 2:39 PM
GROQ is arguably not vulnerable to this type of injection in a security sense, since anyone can just send arbitrary GROQ queries to the API to access your data.
Visibility of private data (e.g. drafts) is protected by
the role-based security system . This system isn't vulnerable to injection, as there is no way that anyone can escape the permission enforcement by crafting a special GROQ query.
However, if you use something like
slug.current in ${slugs}
and this is just doing JavaScript interpolation, then you're potentially exposed to syntax errors caused by things like quotes. You should use real query parameters for this, e.g.
slug.current in $slugs
(this is GROQ syntax, not JS syntax). You would then pass
slugs
as query parameter to the API. This is explained here .
I don't know if there is a document about GROQ and security.
Feb 5, 2024, 10:49 AM
Although if you have an authenticated query and are using this interpolation that would expose potentially secret data though?
Feb 7, 2024, 10:01 AM
Yes. But if a malicious actor has access to run authenticated queries, then you're already in a bad situation, and GROQ interpolation probably isn't your main problem?
Feb 7, 2024, 10:04 AM
Well, if I have an entirely private dataset but with some content that “actually public” and some that are secret, like a “secret.document” ID or some user data.
If we expose a endpoint for blog posts and be “lazy” with using string interpolation instead of query params like this:



const query = `*[_type == "post" && _id > ${lastId}]`
I guess we could pass lastId to the endpoint with something like this:


lastId = `${validLastId}] {
"allDocuments": *[],
}[`

Feb 7, 2024, 10:12 AM
We almost always use queryParams but I haven’t thought too much about this myself
Feb 7, 2024, 10:13 AM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?