Fix Authorization page leaking OAuth secrets via DOM and event logs - #742
Merged
ddon merged 1 commit intoAug 21, 2026
Merged
Conversation
authorization.html.heex rendered the real Google/GitHub/Facebook OAuth client secrets into value= on type="password" inputs - masked on screen only, plaintext in the HTML source (view-source/DevTools). Because the DOM echoed the real secret, editing any other field on the page re-submitted it as part of the validate_settings phx-change event's full-form params, which Phoenix's built-in LiveView event telemetry logger then wrote to the application log. Neither leak is closable via filter_parameters: that's a host-app Application env key, and a dependency's own config isn't merged into a consuming app at boot, so phoenix_kit cannot fix this from a config file. The three secret inputs now render value="" unconditionally, with a placeholder that signals whether a secret is already configured without ever showing it. Client ID/App ID fields are untouched - they are intentionally public. authorization.ex keeps @settings holding the real secret values at all times (test_oauth still reads them to test the live connection), but validate_settings and save_settings now run incoming params through a new preserve_unset_secrets/2 helper first: a blank incoming secret falls back to the currently-held value instead of overwriting/logging it, while a non-blank value (an admin actively typing a new secret) always wins. This also fixes save_settings silently wiping a stored secret whenever the form was submitted without retyping it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
authorization.html.heexrendered the real Google/GitHub/Facebook OAuth client secrets intovalue=ontype="password"inputs.type="password"only masks the on-screen rendering — the real value sits in the HTMLvalue=attribute in plaintext, visible via view-source or DevTools to anyone who can load the page.Because the DOM echoed the real secret back, editing any other field on the page re-submitted it as part of the
validate_settingsphx-changeevent's full-form params (LiveView sends the whole form on every change, not just the changed field), and Phoenix's built-in LiveView event telemetry logger then wrote those params to the application log.Neither leak is closable via
filter_parameters: that's a host-appApplicationenv key, and a dependency's ownconfig/config.exsisn't merged into a consuming app at boot, so this can't be fixed from phoenix_kit's own config. The only real fix is root-cause: never let the real secret round-trip through the DOM/event params in the first place.This is a different problem from #741 — that fix was about not loading the secrets into General/Users assigns unnecessarily. The Authorization page legitimately needs the real values (it manages OAuth credentials, and
test_oauthuses them to test the live connection), so the fix here is safe output, not a key filter.Fix
value=""unconditionally instead of the real stored value. A placeholder communicates whether a secret is already configured, without ever showing it. Client ID / App ID fields are untouched — those are intentionally public.@settingsstill holds the real secret values at all times, sotest_oauthkeeps working unchanged.validate_settingsandsave_settingsnow run incoming params throughpreserve_unset_secrets/2: a blank incoming value for one of the three secret keys falls back to the currently-held real value instead of overwriting/logging it; a non-blank value (an admin actively typing a new secret) always wins. This also fixessave_settingssilently wiping a stored secret whenever the form was submitted without retyping it.Verified
test/integration/phoenix_kit_web/live/settings/authorization_secret_leak_test.exs, 4 tests, 0 failures):ExUnit.CaptureLog-captured logs;mix quality(format,credo --strict, dialyzer): clean.