T09 · Insecure Skill Coding Practices
- Location
scripts/publish_draft.sh:72- Finding
Arbitrary Python Code Execution Through Unquoted Heredoc Interpolation
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Sanity publishing skill is coherent, but it has a serious script-safety flaw and can modify live CMS data with a write token.
Review this skill before installing. Use only a least-privilege Sanity token, prefer a staging dataset, keep draft mode enabled, and avoid passing untrusted filenames or environment overrides until the publish script is fixed to pass values as data instead of interpolating them into Python source.
scripts/publish_draft.sh:72Arbitrary Python Code Execution Through Unquoted Heredoc Interpolation
scripts/publish_draft.sh:78Existing Documents Can Be Unexpectedly Replaced or Only Partially Updated
The skill instructs the agent to run a shell script (bash <skill-dir>/scripts/publish_draft.sh) but does not declare any explicit tool scope or allowed-tools boundary. That increases the chance of unintended shell execution during activation and weakens policy enforcement around a capability that can read files, use environment credentials, and make outbound network requests.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
---
name: sanity-cms
description: Publish content to any Sanity CMS instance. Use when asked to create a Sanity draft, push a document to Sanity, upload an image asset to Sanity, or convert content into a Sanity-formatted document. Works with any document type and schema — not limited to blog posts. Requires SANITY_PROJECT_ID and SANITY_API_TOKEN env vars.
---
# Sanity CMS Skill
The activation text is very broad: it covers creating drafts, pushing documents, uploading assets, converting content, and works with any document type and schema. Broad matching increases the risk that the skill is invoked for loosely related requests, causing content to be sent to a remote CMS or shell commands to run when the user did not clearly intend that outcome.
The skill explicitly directs transmitting documents and optional images to a remote Sanity CMS and using write-enabled API credentials, but it does not require a user-facing warning or confirmation before exfiltrating content. In this context, the skill can move potentially sensitive workspace data to an external service under privileged credentials, making accidental data disclosure or unauthorized publication more likely.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
curl -s -X POST \
"https://${SANITY_PROJECT_ID}.api.sanity.io/v2021-06-07/assets/images/${SANITY_DATASET}" \
-H "Authorization: Bearer ${SANITY_API_TOKEN}" \
-H "Content-Type: image/png" \
The reference explicitly documents write-capable mutations and notes that non-draft IDs publish content immediately, but it does not prominently frame the operational risk of modifying live CMS content. In an agent skill context, this can lead to accidental production changes, unwanted publication, or overwriting existing documents if the agent uses createOrReplace without strong safeguards.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
esac
echo "Uploading image: $COVER_IMAGE" >&2
UPLOAD_RESPONSE=$(curl -s -X POST \
"${BASE_URL}/assets/images/${DATASET}" \
-H "Authorization: Bearer ${SANITY_API_TOKEN}" \
-H "Content-Type: ${CONTENT_TYPE}" \
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
MUTATION_PAYLOAD=$(python3 -c "import json,sys; print(json.dumps(json.loads(sys.stdin.read())['mutation']))" <<< "$MUTATION")
echo "Pushing document to Sanity (dataset: ${DATASET})..." >&2
RESPONSE=$(curl -s -X POST \
"${BASE_URL}/data/mutate/${DATASET}" \
-H "Authorization: Bearer ${SANITY_API_TOKEN}" \
-H "Content-Type: application/json" \
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.
---
name: sanity-cms
description: Publish content to any Sanity CMS instance. Use when asked to create a Sanity draft, push a document to Sanity, upload an image asset to Sanity, or convert content into a Sanity-formatted document. Works with any document type and schema — not limited to blog posts. Requires SANITY_PROJECT_ID and SANITY_API_TOKEN env vars.
---
# Sanity CMS Skill
This shell script requires a write-enabled SANITY_API_TOKEN and sends it in Authorization headers to external Sanity API endpoints. Although the script documents the required environment variable and logs upload/push activity, it does not explicitly warn the user that a credential will be transmitted over the network.