Back to skill

Security audit

Gladia YouTube Transcription (Free)

Security checks for vulnerabilities and agentic risk

Overview

The skill transparently sends user-provided media URLs to Gladia for transcription, with some credential-handling and input-validation cautions but no evidence of hidden or malicious behavior.

Install only if you are comfortable sending media URLs and resulting transcription data to Gladia under your account. Keep GLADIA_API_KEY session-only or in a secrets manager rather than ~/.bashrc, avoid private or sensitive media, and treat URLs from untrusted sources cautiously until the script uses safe JSON encoding and URL validation.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
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: Medium

bash
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_URL from 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_url string 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_value

The 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:// and https:// URLs.
  • Reject control characters and impose a reasonable maximum URL length.
  • Use curl --fail-with-body -sS so 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.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (13)

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · SKILL.md (reported line 79)May include surrounding context.

** section 3. View current month consumption (hours/minutes used)

Alternatively, you can check via API:

bash
curl -X GET "https://api.gladia.io/v2/usage" -H "x-gladia-key: YOUR_API_KEY"

Setup

Step 1: Save Your API Key

Recommended: Set in current session

bash
export GLADIA_API_KEY="your-api-key-here"

Or add to ~/.bashrc (ensure ~/.bashrc is in .gitignore):

bash
echo 'export GLADIA_API_KEY="your-api-key-here"' >> ~/.bashrc
source ~/.bashrc

Note: Storing secrets in shell rc files is discouraged due to risk of accidental commits. Prefer setting the environment variable directly in your session or use a secrets manager.

Step 2: Verify Key Works

Test that your API key is valid by checking usage:

bash
curl -X GET "https://api.gladia.io/v2/usage" -H "x-gladia-key: $GLADIA_API_KEY"

If successful, you'll see your usage information. If you get an auth error, check your API key.

How to Use

Command Line

bash
# Navigate to skil

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/youtube_transcribe.sh (reported line 8)May include surrounding context.

sh
set -e

# Get API key from environment - MUST be set before running
if [ -z "$GLADIA_API_KEY" ]; then
    echo "Error: GLADIA_API_KEY environment variable not set"
    echo "Please set it before running: export GLADIA_API_KEY='your-api-key'"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/youtube_transcribe.sh (reported line 33)May include surrounding context.

sh
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\"}")

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/youtube_transcribe.sh (reported line 51)May include surrounding context.

sh
# Poll for result (max 5 minutes)
for i in {1..30}; do
    RESULT=$(curl -s -X GET "https://api.gladia.io/v2/pre-recorded/$JOB_ID" \
        -H "x-gladia-key: $GLADIA_API_KEY")
    
    STATUS=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status', ''))")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 54)May include surrounding context.

md
1. Visit [gladia.io](https://gladia.io)
2. Click "Try for free" → Sign up with email
3. Go to Dashboard → API Keys
4. Create a new API key
5. Copy the key (format: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`)

### Checking Usage

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

The skill instructs users to send requests containing an API credential to an external third-party service endpoint. External transmission is expected for this skill's function, but it still creates real data exposure and credential-handling risk if users submit sensitive media or misuse the example with real secrets in insecure environments.

Content

Scanner excerpt · SKILL.md (reported line 65)May include surrounding context.

Alternatively, you can check via API:

bash
curl -X GET "https://api.gladia.io/v2/usage" -H "x-gladia-key: YOUR_API_KEY"

Setup

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

Advising users to append GLADIA_API_KEY to ~/.bashrc creates unnecessary session persistence for a secret, increasing the chance of accidental disclosure through backups, dotfile sync, shared accounts, shell history workflows, or mistaken commits. The document partially contradicts itself by offering this approach and then warning against storing secrets in shell rc files.

Content

Scanner excerpt · SKILL.md (reported line 77)May include surrounding context.

export GLADIA_API_KEY="your-api-key-here"

text

**Or add to ~/.bashrc** (ensure ~/.bashrc is in .gitignore):
```bash
echo 'export GLADIA_API_KEY="your-api-key-here"' >> ~/.bashrc
source ~/.bashrc

External Transmission

Medium
Category
Data Exfiltration
Confidence
85% confidence
Finding

This usage-check command transmits the API key to Gladia over the network, which is inherent to authentication but still a real credential exposure surface. In the skill context this is expected and not malicious, yet it can be dangerous if command history, logs, screenshots, or shared terminals expose the secret.

Content

Scanner excerpt · SKILL.md (reported line 89)May include surrounding context.

Test that your API key is valid by checking usage:

bash
curl -X GET "https://api.gladia.io/v2/usage" -H "x-gladia-key: $GLADIA_API_KEY"

If successful, you'll see your usage information. If you get an auth error, check your API key.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

The script sends the user-supplied audio/video URL and the Gladia API credential to an external third-party service for processing. In the context of a transcription skill this behavior is expected, but it still creates a real data-exposure boundary: any content referenced by the URL is disclosed to Gladia, and users may unknowingly submit sensitive or internal media URLs.

Content

Scanner excerpt · scripts/youtube_transcribe.sh (reported line 33)May include surrounding context.

sh
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\"}")

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

The script sends the user-supplied audio/video URL and the Gladia API credential to an external third-party service for processing. In the context of a transcription skill this behavior is expected, but it still creates a real data-exposure boundary: any content referenced by the URL is disclosed to Gladia, and users may unknowingly submit sensitive or internal media URLs.

Content

Scanner excerpt · scripts/youtube_transcribe.sh (reported line 33)May include surrounding context.

sh
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\"}")

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/youtube_transcribe.sh (reported line 51)May include surrounding context.

sh
# Poll for result (max 5 minutes)
for i in {1..30}; do
    RESULT=$(curl -s -X GET "https://api.gladia.io/v2/pre-recorded/$JOB_ID" \
        -H "x-gladia-key: $GLADIA_API_KEY")
    
    STATUS=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status', ''))")

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The manifest description highlights use for "Cantonese/Chinese content without captions," which is a language-specific preference in the natural-language guidance. While not a hard technical restriction, it nudges usage toward particular languages without offering user choice or explaining a policy-based need for that locale focus.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.