T09 · Insecure Skill Coding Practices
- Location
scripts/youtube_transcribe.sh:15- Finding
Untrusted URL Input Is Interpolated Directly into a JSON Request Body
- Content
View full analysis
Vulnerability Details
File Location:
scripts/youtube_transcribe.sh, lines 15-35
Vulnerability Type: JSON injection caused by unsafe input serialization
Risk Level: Mediumbash AUDIO_URL="${1:-}" OUTPUT_FILE="${2:-}" if [ -z "$AUDIO_URL" ]; then echo "Usage: $0 <audio/video_url> [output_file]" echo "Example: $0 \"https://youtube.com/watch?v=xxx\"" echo "Example: $0 \"https://example.com/audio.mp3\" /path/to/output.txt" exit 1 fi # Get script directory for relative paths SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Create transcripts directory if needed TRANSCRIPT_DIR="${SCRIPT_DIR}/transcripts" mkdir -p "$TRANSCRIPT_DIR" echo "Submitting transcription job..." RESPONSE=$(curl -s -X POST "https://api.gladia.io/v2/pre-recorded" \ -H "x-gladia-key: $GLADIA_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"audio_url\": \"$AUDIO_URL\"}")Technical Analysis
The first command-line argument is attacker-controllable and is inserted directly into a JSON string without JSON-safe encoding. Shell quoting prevents ordinary shell metacharacters in
AUDIO_URLfrom becoming commands, so this is not shell command injection. It does not, however, escape JSON quotation marks, backslashes, or control characters.A crafted argument can terminate the intended
audio_urlstring and introduce additional JSON properties. For example, an argument shaped like the following can alter the structure of the request:text https://example.test/audio.mp3", "attacker_property": "attacker_valueThe resulting request body would be structurally equivalent to:
json { "audio_url": "https://example.test/audio.mp3", "attacker_property": "attacker_value" }Whether an injected property changes processing depends on which Gladia request fields the endpoint recognizes. At minimum, malformed input can invalidate the ...[truncated 1851 chars]
- Remediation
View remediation
Remediation Suggestions
Construct the request body with a JSON serializer rather than string interpolation:
bash case "$AUDIO_URL" in http://*|https://*) ;; *) echo "Error: only HTTP and HTTPS media URLs are supported" >&2 exit 1 ;; esac PAYLOAD=$(python3 -c \ 'import json, sys; print(json.dumps({"audio_url": sys.argv[1]}))' \ "$AUDIO_URL") RESPONSE=$(curl --fail-with-body -sS \ -X POST "https://api.gladia.io/v2/pre-recorded" \ -H "x-gladia-key: $GLADIA_API_KEY" \ -H "Content-Type: application/json" \ --data-binary "$PAYLOAD")This ensures quotation marks, backslashes, and control characters are encoded as data rather than interpreted as JSON syntax.
Additional hardening should include:
- Restrict input to explicitly supported
http://andhttps://URLs. - Reject control characters and impose a reasonable maximum URL length.
- Use
curl --fail-with-body -sSso HTTP failures produce a nonzero status while preserving diagnostic output. - Validate the response schema before trusting the returned job identifier.
- Apply API-side usage limits or billing alerts to reduce the impact of unintended jobs.
- Avoid displaying complete API error responses if the provider could include sensitive account information.
- Restrict input to explicitly supported
