GROQ queries and security in Sanity.io
5 replies
Last updated: Feb 7, 2024
N
Is there a place I can read about GROQ queries and security?I stumbled upon queries like
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.
*[_type == "page" && slug.current in ${slugs}]
Feb 4, 2024, 2:39 PM
A
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
I don't know if there is a document about GROQ and security.
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
slugsas 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
S
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
A
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
S
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:
I guess we could pass lastId to the endpoint with something like this:
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}]`
lastId = `${validLastId}] { "allDocuments": *[], }[`
Feb 7, 2024, 10:12 AM
S
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.