T09 · Insecure Skill Coding Practices
- Location
SKILL.md:66- Finding
Unsafe JSON Construction from Untrusted Values
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 66–74
Vulnerability Type: JSON injection through unsafe string interpolation
Risk Level: Mediumbash curl -s -X POST 'https://api.pincaimao.com/agents/v1/chat/chat-messages' \ -H "Authorization: Bearer $PCM_INTERVIEW_REPORT_KEY" \ -H 'Content-Type: application/json' \ -d "{ \"query\": \"$FILE_NAME\", \"inputs\": { \"job_info\": \"$JOB_INFO\", \"file_urls\": \"$COS_KEY\" }, \"response_mode\": \"blocking\" }" | python3 -c "import sys,json; print(json.load(sys.stdin)['answer'])"Technical Analysis
The request body is constructed by directly interpolating
FILE_NAME,JOB_INFO, andCOS_KEYinto a JSON string. These values are not encoded with a JSON serializer.JOB_INFOcontains user-provided content, whileFILE_NAMEandCOS_KEYare obtained from the upload API response. If any interpolated value contains quotation marks, backslashes, control characters, or crafted JSON syntax, it can terminate its intended string value and alter the structure of the request. Ordinary legitimate input containing quotation marks or line breaks can also produce malformed JSON.This is not direct shell command injection because shell syntax introduced through variable expansion is not reparsed as shell code. The vulnerability is confined to the construction and semantics of the authenticated JSON API request.
Attack Path
- An attacker supplies a crafted job description or an interview file with a crafted filename.
- The job description is assigned to
JOB_INFO, or the upload service returns the filename asFILE_NAME. - The Skill inserts the value directly into the JSON request without serialization or escaping.
- The crafted value closes its intended JSON string and injects additional JSON syntax, or causes the body to become malformed.
- The request is submitted to the Pincaimao API using t ...[truncated 799 chars]
- Remediation
View remediation
Remediation Suggestions
Construct the request body with a JSON serializer rather than shell string interpolation. Pass each value to the serializer as a separate argument so quotation marks, backslashes, line breaks, and control characters are encoded correctly.
bash PAYLOAD=$(python3 -c ' import json import sys print(json.dumps({ "query": sys.argv[1], "inputs": { "job_info": sys.argv[2], "file_urls": sys.argv[3] }, "response_mode": "blocking" })) ' "$FILE_NAME" "$JOB_INFO" "$COS_KEY") curl --fail-with-body --silent --show-error \ -X POST 'https://api.pincaimao.com/agents/v1/chat/chat-messages' \ -H "Authorization: Bearer $PCM_INTERVIEW_REPORT_KEY" \ -H 'Content-Type: application/json' \ --data-binary "$PAYLOAD" | python3 -c "import sys,json; print(json.load(sys.stdin)['answer'])"Additionally:
- Validate that
FILE_NAMEandCOS_KEYreturned by the upload service have the expected types and reasonable length limits. - Apply an appropriate size limit to
JOB_INFO. - Reject malformed upload responses before constructing the second request.
- Use
curl --fail-with-body --silent --show-errorand verify the HTTP response before parsing it as a successful API result. - Keep the API key restricted to only the endpoints and operations required for file upload and report generation, if the service supports scoped credentials.
- Validate that
