T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/typefully.sh:52
- Finding
- Schedule Parameter Allows Authenticated JSON Body Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/typefully.sh:52-62`, `scripts/typefully.sh:178-182`, and `scripts/typefully.sh:215-221` **Vulnerability Type**: Improper input validation and unsafe JSON construction **Risk Level**: Medium ### Complete Vulnerable Code The schedule validator accepts any value beginning with a timestamp-like prefix because the regular expression is not anchored at the end: ```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 input is interpolated 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 occurs 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 timestamp regular expression validates only the beginning of the supplied value. It does not require the entire input to conform to an ISO 8601 timestamp. Consequently, a value may begin with a timestamp-like string and contain arbitrary trailing characters, including quotation marks and additional JSON properties. After validation, the value is embedded into a JSON document through shell string concatenation. No JSON serializer is used at these sinks, so embedded quotation marks, commas, braces, and property names retain their JSON syntax. For example, an input shaped like the following passes the prefix validation: ```text 2026-03-01T09:0 ...[truncated 2007 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace prefix-only validation with full-string validation. Require a timezone and reject all trailing data. For example: ```bash if [[ "$val" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$ ]]; then return 0 fi ``` 2. Parse the value with a date-time parser rather than relying exclusively on a regular expression. This will reject impossible dates and times in addition to malformed syntax. 3. Construct all request bodies using a JSON serializer. For example, Python can safely encode the value: ```bash body=$(python3 - "$when" <<'PY' import json import sys print(json.dumps({"publish_at": sys.argv[1]})) PY ) api PUT "/social-sets/${SOCIAL_SET_ID}/drafts/${draft_id}" -d "$body" ``` 4. Apply the same serializer-based approach to `cmd_create_draft` so that every user-controlled value is encoded as data rather than concatenated as JSON syntax. 5. Add regression tests containing quotation marks, braces, commas, control characters, malformed timestamps, missing timezones, and valid timestamps with malicious suffixes. Tests should verify that malformed values are rejected and that valid values produce exactly one `publish_at` property. ]]>
