The internal API (LB -> main), the admin live/vod/timeshift proxies, the
admin API and RTMP publish/play checked their shared secrets —
live_streaming_pass, api_pass, the RTMP allow-list passwords — with ==.
That compares two numeric-looking strings as numbers ("1000" == "1e3") and
stops at the first differing byte, which a patient client can time.
They now go through AuthService::secretMatches(): hash_equals on strings,
false for anything a query string can make that is not one (null, an array),
and false for a secret that is not configured. Each caller keeps its own
"no secret required" rule (an empty api_pass, an allow-list entry with no
password), exactly as before.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EuZvjFSdodqgpyXtaoH1Xt