Sanity CMS
v1.0.0Query and manage Sanity CMS content via GROQ queries and the Sanity HTTP API. Use when asked to fetch content from a Sanity dataset, create or update documen...
MIT-0
Security Scan
OpenClaw
Suspicious
medium confidencePurpose & Capability
The skill name, description, and SKILL.md all describe Sanity CMS operations and the examples require SANITY_PROJECT_ID, SANITY_DATASET, and SANITY_API_TOKEN — these are appropriate for the stated purpose. However, the registry metadata at the top of the package declares no required env vars, which is inconsistent with the instructions.
Instruction Scope
SKILL.md contains curl examples and GROQ queries that only target Sanity endpoints and explain required env vars. The instructions do not instruct reading unrelated system files, other credentials, or exfiltrating data to unexpected endpoints; scope stays within Sanity CMS functionality.
Install Mechanism
No install spec and no code files — the skill is instruction-only and runs curl against Sanity. This is low risk from an installation perspective (nothing is downloaded or written to disk).
Credentials
The SKILL.md explicitly requires SANITY_PROJECT_ID, SANITY_DATASET, and SANITY_API_TOKEN (sensitive credentials) which are appropriate for Sanity access. The concern is the registry metadata did not declare these required env vars or a primary credential, leaving a mismatch between what the skill needs and what was advertised. Because the skill will use an API token that can permit mutations, confirm the token's scope (use least privilege, e.g., Viewer for read-only use).
Persistence & Privilege
The skill does not request persistent presence (always:false), does not modify other skills or system configs, and has no special OS restrictions. Autonomous invocation is allowed by platform default but is not combined with other privilege-extending factors here.
What to consider before installing
This skill appears to be a straightforward set of curl examples for Sanity, but the package metadata omitted the env vars the SKILL.md says are required — treat that as a red flag. Before installing or providing secrets: (1) verify the skill's source or repository (none provided here); (2) create and provide a Sanity API token with the minimal scope you need (Viewer for reads, a narrowly scoped Editor for specific writes), not a master/admin token; (3) test the skill against a non-production project/dataset first; (4) confirm network endpoints in the instructions match sanity.io (they do in SKILL.md); and (5) if you need auditability, ask the publisher to correct the registry metadata to declare required env vars so the required permissions are explicit. If you cannot verify the author or do not want to provide a token, do not install/use the skill.Like a lobster shell, security has layers — review code before you run it.
cmscontentgroqheadless-cmslatestsanity
License
MIT-0
Free to use, modify, and redistribute. No attribution required.
SKILL.md
Sanity CMS Skill
Sanity API base: https://<projectId>.api.sanity.io/v2021-10-21
Env Vars
SANITY_PROJECT_ID=abc123
SANITY_DATASET=production # or staging
SANITY_API_TOKEN=sk... # from sanity.io/manage > API > Tokens
SANITY_BASE="https://$SANITY_PROJECT_ID.api.sanity.io/v2021-10-21"
GROQ Queries (Read)
Fetch All Documents of a Type
curl -G "$SANITY_BASE/data/query/$SANITY_DATASET" \
-H "Authorization: Bearer $SANITY_API_TOKEN" \
--data-urlencode 'query=*[_type == "post"]{_id, title, slug, publishedAt}'
Fetch Single Document by Slug
curl -G "$SANITY_BASE/data/query/$SANITY_DATASET" \
-H "Authorization: Bearer $SANITY_API_TOKEN" \
--data-urlencode 'query=*[_type == "post" && slug.current == $slug][0]' \
--data-urlencode '$slug="my-blog-post"'
Complex Query with References
# Posts with author name resolved
*[_type == "post"]{title, "author": author->name, "category": category->title, body}
Count Documents
count(*[_type == "post"])
Mutations (Create/Update/Delete)
Create Document
curl -X POST "$SANITY_BASE/data/mutate/$SANITY_DATASET" \
-H "Authorization: Bearer $SANITY_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mutations": [{
"create": {
"_type": "post",
"_id": "drafts.new-post-id",
"title": "New Blog Post",
"slug": {"_type": "slug", "current": "new-blog-post"},
"publishedAt": "2026-03-27T00:00:00Z"
}
}]
}'
Update Document (Patch)
curl -X POST "$SANITY_BASE/data/mutate/$SANITY_DATASET" \
-H "Authorization: Bearer $SANITY_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mutations": [{
"patch": {
"id": "<document_id>",
"set": {"title": "Updated Title", "status": "published"}
}
}]
}'
Delete Document
-d '{"mutations": [{"delete": {"id": "<document_id>"}}]}'
Publish Draft
# Move draft to published: delete draft, create published version
-d '{
"mutations": [
{"delete": {"id": "drafts.<doc_id>"}},
{"createOrReplace": {"_id": "<doc_id>", "_type": "post", ...fields}}
]
}'
GROQ Syntax Reference
- Filter:
*[_type == "post" && status == "published"] - Sort:
| order(publishedAt desc) - Slice:
[0...10] - Projection:
{title, "authorName": author->name} - References:
->dereferences a reference field $paramfor query parameters (pass as$paramName=value)
Tips
- IDs starting with
drafts.are unpublished drafts - Use
_revfield to detect conflicts on concurrent edits - Token needs "Editor" role minimum for mutations; "Viewer" for queries only
- GROQ playground: sanity.io/manage > your project > Vision tab
Files
1 totalSelect a file
Select a file to preview.
Comments
Loading comments…
