T09 · Insecure Skill Coding Practices
- Location
SKILL.md:24- Finding
Unsafe Shell Interpolation in CRM Request Payloads
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 24–27 and 36–39
Vulnerability Type: Shell argument injection and unsafe JSON construction
Risk Level: MediumVulnerable Code
sh curl -s -X POST "https://services.leadconnectorhq.com/contacts/" \ -H "Authorization: Bearer $GHL_API_KEY" -H "Version: 2021-07-28" -H "Content-Type: application/json" \ -d '{"firstName":"$FIRST","lastName":"$LAST","email":"$EMAIL","phone":"$PHONE","locationId":"'$GHL_LOCATION_ID'","tags":["$TAGS"],"source":"$SOURCE"}' | jq .sh curl -s -X POST "https://services.leadconnectorhq.com/opportunities/" \ -H "Authorization: Bearer $GHL_API_KEY" -H "Version: 2021-07-28" -H "Content-Type: application/json" \ -d '{"pipelineId":"$PIPELINE_ID","locationId":"'$GHL_LOCATION_ID'","name":"$DEAL_NAME","stageId":"$STAGE_ID","contactId":"$CONTACT_ID","status":"open"}' | jq .Technical Analysis
The JSON request bodies are assembled through inconsistent shell quoting. Most variables, including
$FIRST,$EMAIL, and$CONTACT_ID, appear inside single-quoted strings and therefore are not expanded by a POSIX-compatible shell. They are transmitted as literal variable names rather than their intended values.In contrast,
$GHL_LOCATION_IDis placed outside the single-quoted portions and expanded without double quotes:sh ... "locationId":"'$GHL_LOCATION_ID'" ...Because this expansion is unquoted, shell word splitting and pathname expansion apply. A malformed or attacker-controlled value containing whitespace, wildcard characters, or strings resembling command-line options can split the intended
-dargument into multiple arguments. Additional resulting arguments may then be interpreted bycurlas options or URLs.The issue does not directly invoke shell metacharacters embedded in the variable as executable syntax, because shell parsing occurs before parameter expansion. Nevertheless, argument injection into
curlremains possible and c ...[truncated 1721 chars]- Remediation
View remediation
Remediation Suggestions
Construct every JSON payload with a JSON-aware utility such as
jq, and double-quote every shell expansion. Do not interpolate values directly into JSON strings.A hardened contact-creation example is:
sh payload=$(jq -n \ --arg firstName "$FIRST" \ --arg lastName "$LAST" \ --arg email "$EMAIL" \ --arg phone "$PHONE" \ --arg locationId "$GHL_LOCATION_ID" \ --arg tag "$TAGS" \ --arg source "$SOURCE" \ '{ firstName: $firstName, lastName: $lastName, email: $email, phone: $phone, locationId: $locationId, tags: [$tag], source: $source }') curl --fail-with-body -sS -X POST \ "https://services.leadconnectorhq.com/contacts/" \ -H "Authorization: Bearer $GHL_API_KEY" \ -H "Version: 2021-07-28" \ -H "Content-Type: application/json" \ --data-binary "$payload" | jq .Apply the same pattern to opportunity creation and every other JSON body. In addition:
- Validate
GHL_LOCATION_IDagainst its expected identifier syntax before use. - Use
--data-binary "$payload"so the entire body is passed as one argument. - Use
--fail-with-body -sSso HTTP and transport failures are visible. - URL-encode all values used in query strings instead of directly concatenating environment variables.
- Validate identifiers used in URL paths to prevent path manipulation.
- Keep
GHL_API_KEYscoped to the minimum CRM permissions required and rotate it if unintended disclosure is suspected. - Consider using a dedicated API client or wrapper script rather than instructing users or Agents to copy shell commands containing credentials.
- Validate
