AzuraCast Vulnerable to Liquidsoap Code Injection via Incomplete cleanUpString-to-toRawString Migration in Remote Relay Password Field
Date: 2026-05
Affected: composer/azuracast/azuracast
Attack vector: rce
Category: vulnerability-disclosure
Severity: High
CWE: CWE-94
CVSS: 8.8 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

## Summary The `cleanUpString()` method in `ConfigWriter.php` uses an ungreedy regex to strip Liquidsoap string interpolation patterns (`#{...}`) from user input. This regex can be bypassed via nested interpolation syntax (`#{#{EXPR}}`), allowing injection of arbitrary Liquidsoap code. Commit `ff49ef4` migrated most user-controlled fields to the safe `toRawString()` method but left the remote relay password field using the vulnerable `cleanUpString()`. A user with the `RemoteRelays` station permission can achieve arbitrary code execution in the Liquidsoap process, leak internal API keys, or disrupt station operation. ## Details ### The Vulnerable Sanitizer `cleanUpString()` at `backend/src/Radio/Backend/Liquidsoap/ConfigWriter.php:1349-1367`: ```php public static function cleanUpString(?string $string): string { $string = str_replace(['"', "\n", "\r"], ['\'', '', ''], $string ?? ''); // Remove strings that are interpolated $string = preg_replace( '/#{(.*)}/U', // Ungreedy: matches minimum chars to first } '$1', $string ); $string = preg_replace( '/\$\((.*)\)/U', '$1', $string ?? '' ); return $string ?? ''; } ``` The `/U` (ungreedy) flag causes `.*` to match the **minimum** characters until the first `}`. With nested input `#{#{EXPR}}`: 1. Regex finds `#{` at position 0 2. Ungreedy `.*` matches `#{EXPR` (stops at the **first** `}`) 3. Full match consumed: `#{#{EXPR}` — replacement with capt


Mitigations:

Architectural layers (MAESTRO):