T09 · Insecure Skill Coding Practices
- Location
SKILL.md:72- Finding
Shell Command Injection Through Unsafely Interpolated Booking Data
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 72–84
Vulnerability Type: Shell command injection through unsafe user-input interpolation
Risk Level: Highbash curl -s -X POST "https://api.calendly.com/invitees" \ -H "Authorization: Bearer $CALENDLY_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "{EVENT_TYPE_URI}", "start_time": "{TIME_UTC}", "invitee": { "name": "{NAME}", "email": "{EMAIL}", "timezone": "{TIMEZONE_IANA}" } }'Technical Analysis
The documented workflow places booking values derived from natural-language input directly inside a single-quoted shell argument. No JSON serialization, shell-safe argument construction, or validation requirement is specified for
{NAME},{EMAIL}, or{TIMEZONE_IANA}.A single quote in one of these fields can terminate the shell string before the intended end of the JSON body. Shell control operators following that quote can then be interpreted as commands rather than booking data. This creates a command-injection risk if an agent implements the documented template through direct placeholder substitution.
Even non-malicious data containing an apostrophe can break the command or produce malformed JSON. JSON escaping alone would not fix the command-injection issue because JSON escaping does not make a value safe for interpolation into shell syntax.
Attack Path
- An attacker submits a booking request containing shell syntax in a user-controlled field, such as a crafted attendee name containing a single quote, a command separator, and a shell command.
- The skill extracts that text as
{NAME}or another booking field. - The agent substitutes the value directly into the documented
curl -d '...'command. - The injected single quote closes the shell argument.
- The shell interprets the following control operator and command as executable syntax.
- The ...[truncated 1179 chars]
- Remediation
View remediation
Remediation Suggestions
-
Do not generate request bodies by substituting user-controlled values into shell source code.
-
Prefer a Calendly SDK or an HTTP client library that accepts an in-memory object and serializes it as JSON without invoking a shell.
-
If
curlmust be used, construct the body with a JSON-aware encoder such asjqand pass each value through a separately quoted argument. For example:bash payload="$(jq -n \ --arg event_type "$EVENT_TYPE_URI" \ --arg start_time "$TIME_UTC" \ --arg name "$NAME" \ --arg email "$EMAIL" \ --arg timezone "$TIMEZONE_IANA" \ '{ event_type: $event_type, start_time: $start_time, invitee: { name: $name, email: $email, timezone: $timezone } }')" curl --silent --show-error --fail-with-body \ -X POST "https://api.calendly.com/invitees" \ -H "Authorization: Bearer $CALENDLY_API_TOKEN" \ -H "Content-Type: application/json" \ --data-binary "$payload" -
Execute commands through an argument-array API rather than through a shell whenever the hosting framework supports it.
-
Validate email addresses, accept only supported IANA timezone identifiers, parse times into a strict ISO 8601 representation, and validate returned Calendly resource URIs before use.
-
Reject control characters and enforce reasonable length limits for attendee names and other text fields as defense in depth.
-
Avoid logging authorization headers, tokens, or complete sensitive booking data.
-
Run the agent with least privilege and restrict its filesystem and outbound-network access to reduce the impact of any command-execution flaw.
-
