Skip to content

Subsonic auth fails when SYSTEM_PASSWORD contains $ followed by uppercase/digit/underscore #144

@boralyl

Description

@boralyl

Summary

After upgrading to v1.0.1, manual runs triggered from the web UI fail Subsonic
authentication with Wrong username or password, even when the same credentials
worked previously (pre-1.0.0 via docker-compose env vars).

Root cause: passwords containing $ followed by an uppercase letter, digit, or
underscore get partially eaten when the .env file is parsed, because the wizard
writes the value to disk un-quoted. Confirmed by changing password to not have any
special characters. Also confirmed that if I wrap the password in single quotes it works
as expected.

Reproduction

  1. Set up Explo v1.0.0 with the web UI enabled.
  2. In the wizard's media-system step, enter a Subsonic/Navidrome password that
    contains $ followed by A-Z, 0-9, or _ (e.g. pa$$Word1, foo$BAR,
    secret$1).
  3. Trigger a manual run from the UI.
  4. Logs show:
WARN SearchPlaylist failed: Wrong username or password
WARN SearchSongs failed: Wrong username or password
WARN [subsonic] failed to schedule a library scan: Wrong username or password

I should note that the issue mentions SYSTEM_PASSWORD, but this would be an issue for any env variable that has this pattern.

I'm not strong in go, so below is what claude thinks the problem is (which for the record sounds like a reasonable assessment to me)


Root cause

updateEnvKeys in src/web/backend/server.go:451-501 writes each env value
verbatim:

lines[i] = key + "=" + val

No quoting or escaping is applied. cleanenv.ReadConfig (in
src/config/config.go:184) then parses the file with joho/godotenv, which
runs every unquoted value through expandVariables. Its regex —

(\\)?(\$)(\()?\{?([A-Z0-9_]+)?\}?

— expands any $ followed by [A-Z0-9_]+ as a variable reference, silently
replacing it with the empty string when the referenced var is unset.

Verified directly against godotenv@v1.5.1:

Raw .env value Parsed result
abc$^!*xyz abc$^!*xyz (ok)
p$assword p$assword (ok)
p$ASSWORD p (mangled)
'p$ASSWORD' p$ASSWORD (ok — single quotes disable expansion)
"p$ASSWORD" p (still expanded — double quotes don't help)

Pre-1.0.0 deployments commonly set SYSTEM_PASSWORD via docker-compose
environment: blocks, which bypass godotenv entirely — that's why this only
surfaces after migrating to the wizard-generated .env.

The same bug affects any field with these characters: SYSTEM_PASSWORD,
API_KEY, SLSKD_API_KEY, YOUTUBE_API_KEY, UI_PASSWORD, MATRIX_ACCESSTOKEN,
DISCORD_BOT_TOKEN, etc.

Workaround

Manually edit /opt/explo/.env and wrap affected values in single quotes:

SYSTEM_PASSWORD='my$Real$Password'

Double quotes don't work — godotenv still expands $VAR inside them.

Suggested fix

In updateEnvKeys (src/web/backend/server.go:476), single-quote values that
contain any of: $, #, ", leading/trailing whitespace, or newlines, and
escape embedded single quotes. Re-saving via the wizard should round-trip
existing values safely.

Environment

  • Explo v1.0.1
  • Music system: Navidrome (Subsonic API)
  • Deployment: Docker, web UI enabled
  • Config written by the v1.0.0 setup wizard

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions