T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/typefully.sh:56
- Finding
- Unescaped Schedule Value Permits JSON Request-Body Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/typefully.sh:56-67`, `scripts/typefully.sh:172-177`, and `scripts/typefully.sh:211-216` **Vulnerability Type**: JSON request-body injection caused by incomplete validation and unsafe string interpolation **Risk Level**: Medium ### Vulnerable Code Schedule validation only verifies the beginning of an ISO-8601-like value: ```bash validate_schedule() { local val="$1" case "$val" in next-free-slot|now) return 0 ;; esac # ISO 8601 pattern if [[ "$val" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2} ]]; then return 0 fi die "Invalid schedule value: $val (expected ISO 8601, 'next-free-slot', or 'now')" } ``` The accepted value is then inserted directly into JSON when creating a draft: ```bash local body="{\"platforms\":{${platform_json}}" if [[ -n "$schedule" ]]; then validate_schedule "$schedule" body+=",\"publish_at\":\"${schedule}\"" fi body+="}" ``` The same unsafe interpolation is used when scheduling an existing draft: ```bash cmd_schedule_draft() { local draft_id="$1" when="$2" validate_draft_id "$draft_id" validate_schedule "$when" api PUT "/social-sets/${SOCIAL_SET_ID}/drafts/${draft_id}" \ -d "{\"publish_at\":\"${when}\"}" } ``` ### Technical Analysis The ISO-8601 regular expression is anchored only at the beginning of the input. Consequently, any value beginning with a timestamp-shaped prefix is accepted, even when arbitrary characters, quotation marks, or additional JSON properties follow it. After validation, the schedule value is concatenated directly into a JSON string without JSON encoding. An input such as: ```text 2026-03-01T09:00:00Z","attacker_field":"value ``` causes the scheduling request body to become: ```json { "publish_at": "2026-03-01T09:00:00Z", "attacker_field": "value" } ``` This is JSON injection rather than shell command injection. The generated body remains one quoted argument to `curl`, so the issue does not ...[truncated 1839 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require the entire schedule value to match an explicitly supported format. At minimum, anchor the regular expression at both ends: ```bash if [[ "$val" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|[+-][0-9]{2}:[0-9]{2})$ ]]; then return 0 fi ``` 2. Prefer parsing the value with a date/time library so invalid calendar dates and times are rejected rather than relying exclusively on a regular expression. 3. Never construct JSON by concatenating untrusted values. Generate request bodies with a JSON serializer, such as Python's `json` module: ```bash body=$(python3 - "$when" <<'PY' import json import sys print(json.dumps({"publish_at": sys.argv[1]})) PY ) ``` 4. Apply serializer-based construction consistently to both draft creation and draft scheduling. Values should still be semantically validated even when safely encoded. 5. Add regression tests covering: - Valid UTC and offset timestamps. - `now` and `next-free-slot`. - Trailing text after an otherwise valid timestamp. - Embedded quotation marks, backslashes, newlines, and JSON delimiters. - Invalid dates and invalid timezone offsets. - Attempts to inject additional JSON properties. ]]>
