Skip to content

Anchor OIDC filter_parameters so host params like code_id and state_eq stay visible - #27

Merged
senid231 merged 4 commits into
mainfrom
copilot/filter-parameters-hide-host-params
Oct 9, 2026
Merged

senid231 merged 4 commits into
mainfrom
copilot/filter-parameters-hide-host-params

Conversation

Copilot AI commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

The engine added its OIDC keys to filter_parameters as symbols, which ActiveSupport::ParameterFilter matches as case-insensitive substrings. So :code and :state also hid host params such as code_id, postal_code and state_eq, and a host couldn't override it from its own initializers.

The keys are now exact-key regexps in two groups:

  • code_verifier, id_token, access_token, refresh_token: filtered at any depth. Nested, they are always secrets.
  • code, state, session_state, nonce: filtered only as top-level params, where the IdP callback sends them. Nested, these names are usually host attributes (data.attributes.state, order[code]), which is the case filter_parameters symbols hide host params like code_id and state_eq #26 reports. The regexp contains \., so ParameterFilter matches it against the dotted full key.

code_verifier (read from params by omniauth_openid_connect with PKCE) and session_state were covered by the old substring match, so they are now listed explicitly.

Behavior change: hosts that relied on the substring match to hide params like invite_code must add their own filters. The CHANGELOG says so.

Verified with a spec that runs the real filter, raw and precompiled, plus rake spec:all.

Fixes #26

Co-authored-by: senid231 <8393857+senid231@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix filter parameters to not hide host params like code_id and state_eq Anchor OIDC filter_parameters so host params like code_id and state_eq stay visible Oct 8, 2026
Copilot AI requested a review from senid231 October 8, 2026 11:12
@senid231
senid231 marked this pull request as ready for review October 8, 2026 15:28
ActiveAdmin forms nest attributes (order[state], product[code]), so an exact-key match at any depth still hid host params. The PKCE code_verifier and session_state were covered by the old substring match and must stay filtered.

Co-Authored-By: Clanker

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The implementation exposes nested exact OIDC keys, contradicting the stated requirement to filter them at every nesting depth.

4 open findings
What changed in this PR

Narrows OIDC parameter filtering to avoid hiding similarly named host parameters.

Changes:

  • Replaces symbol filters with anchored regex filtering.
  • Adds raw and precompiled filter tests.
  • Updates documentation and changelog.
File Description
lib/​activeadmin/​oidc/​engine.rb Introduces exact, top-level OIDC filters.
spec/​security_spec.rb Tests filtering and host parameter visibility.
README.md Documents filtering behavior.
CHANGELOG.md Records the behavior change.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/activeadmin/oidc/engine.rb Outdated
Comment on lines +139 to +142
# ActiveSupport::ParameterFilter matches a regexp containing "\." against the dotted
# full key (order.state), so this hides only top-level keys, where the IdP callback puts them.
oidc_params = %w[code code_verifier state session_state nonce id_token access_token refresh_token]
app.config.filter_parameters |= [/\A(?!.*\.)(?:#{Regexp.union(oidc_params).source})\z/i]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partly fixed in a2c78ae. Nested code_verifier, id_token, access_token and refresh_token are filtered again at any depth, since a nested token is always a secret.

code, state, session_state and nonce stay top-level only on purpose. #26 does not ask for nested filtering: "per key at any depth" there only explains why the callback params stay hidden. Its example is JSON:API, where a host resource with a code or state attribute shows up as data.attributes.state. Hiding that is the bug #26 reports. The IdP callback sends these keys only at the top level.

Comment thread spec/security_spec.rb Outdated
Comment on lines +23 to +27
it "filters the top-level OIDC keys and leaves host params visible (#{form} filters)" do
filter = ActiveSupport::ParameterFilter.new(compile.call(Rails.application.config.filter_parameters))
result = filter.filter(oidc_keys.index_with("secret").merge(host_params))

expect(result).to eq(oidc_keys.index_with("[FILTERED]").merge(host_params))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a2c78ae for the token keys: the spec now nests code_verifier, id_token, access_token and refresh_token under auth and expects them filtered, in both raw and precompiled form. Nested code and state are still expected visible, for the reason in the engine thread.

Comment thread CHANGELOG.md Outdated
Comment thread README.md Outdated
A nested id_token or refresh_token is always a secret, so only the generic callback names (code, state, session_state, nonce) need the top-level limit that keeps host attributes like data.attributes.state visible.

Co-Authored-By: Clanker
@senid231
senid231 merged commit 6e30e4e into main Oct 9, 2026
6 checks passed
@senid231
senid231 deleted the copilot/filter-parameters-hide-host-params branch October 9, 2026 10:10
@senid231 senid231 mentioned this pull request Oct 9, 2026
senid231 added a commit that referenced this pull request Oct 9, 2026
Release 3.0.1

Ships the exact-key filter_parameters fix from #27. Params whose names only contain code, state, nonce or a token name, and nested code, state, session_state and nonce, are no longer hidden in logs. The CHANGELOG tells hosts how to filter any that carry secrets.

Co-Authored-By: Clanker
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

filter_parameters symbols hide host params like code_id and state_eq

3 participants