T09 · Insecure Skill Coding Practices
Warning
- Location
- examples.md:118
- Finding
- Shell Command Injection Through Unsafely Interpolated Firestore Input<![CDATA[ ## Vulnerability Details **File Location**: `examples.md:118-139` (operational example), reinforced by command-construction instructions in `SKILL.md:102-111` **Vulnerability Type**: Shell command injection caused by unsafe interpolation into JSON bodies and URLs **Risk Level**: Medium ### Vulnerable Code The skill instructs the agent to construct a shell command from requested Firestore values and identifiers: ```markdown 3. **Construct the curl command** — Build the appropriate curl command based on the operation: - Use the correct HTTP method (POST for create/query, GET for read, PATCH for update, DELETE for delete) - Include the `Authorization: Bearer $ACCESS_TOKEN` header - Set `Content-Type: application/json` for requests with body - Use the correct API endpoint for the project and collection ``` The corresponding operational example directly embeds document data and a document identifier into shell syntax: ```markdown ### Example 5: Creating a document with a specific ID **User prompt:** "Create a settings document with ID app_config containing theme as dark and notifications enabled" **Expected agent behavior:** 1. Run `gcloud config list --format='text(core.account,core.project)'` and show the active context to the user 2. Get the project ID from the output 3. Construct the curl command with documentId parameter: ```bash ACCESS_TOKEN=$(gcloud auth print-access-token) curl -X POST \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "fields": { "theme": { "stringValue": "dark" }, "notifications": { "booleanValue": true } } }' \ "https://firestore.googleapis.com/v1/projects/my-project/databases/(default)/documents/settings?documentId=app_config" ``` 4. Present the command to the user 5. **Wait for user approval** before executing (this is a create operation) ``` ### Technical Analysis Firestore field values are placed in ...[truncated 2740 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Use a trusted JSON serializer** - Construct request bodies with a tool such as `jq`, using `--arg`, `--argjson`, and structured object construction. - Never concatenate user-controlled values directly into shell-quoted JSON. - Store the generated body in a temporary file with restrictive permissions or pass serialized output through standard input. 2. **Encode URL components** - Percent-encode project IDs, database IDs, collection names, document IDs, field paths, and query parameter values independently. - Prefer `curl --get --data-urlencode` for query parameters where supported. - Do not treat URL quoting as shell-safety or URL encoding. 3. **Apply strict identifier validation** - Validate project and resource identifiers against documented Google Cloud and Firestore formats. - Reject shell metacharacters, control characters, line breaks, command-substitution syntax, and unexpected path separators. - Use allowlists rather than attempting to enumerate dangerous characters. 4. **Avoid dynamic shell evaluation** - Invoke `curl` through an argument-array API when implementation tooling permits. - Never use `eval`, `sh -c`, or equivalent re-parsing of generated command strings. - If commands must be displayed for approval, retain a structured argument list and execute that exact structure rather than re-parsing displayed text. 5. **Strengthen approval output** - Display user-controlled values separately from the rendered command. - Clearly identify all target resource components and whether the operation is read-only or destructive. - Preserve the existing active-account and project confirmation requirements, but do not rely on approval as the primary injection defense. 6. **Add adversarial tests** - Test values containing single and double quotes, backticks, dollar signs, command substitutions, newlines, backslashes, Unicode control characters, ampersands, semicolons, and U ...[truncated 126 chars]
