Skip to content

[SSO] Fix OIDC group sync privilege escalation via case folding#36509

Open
mtabebe wants to merge 1 commit into
MaterializeInc:mainfrom
mtabebe:ma/sso/fix-lowercase
Open

[SSO] Fix OIDC group sync privilege escalation via case folding#36509
mtabebe wants to merge 1 commit into
MaterializeInc:mainfrom
mtabebe:ma/sso/fix-lowercase

Conversation

@mtabebe
Copy link
Copy Markdown
Contributor

@mtabebe mtabebe commented May 11, 2026

Problem:
JWT group names were lowercased before catalog lookup. When two roles differ only by case (e.g. admin and "Admin"), the lowercase map built by roles_by_lowercase_name silently picked the wrong role due to BTreeMap last-writer-wins semantics.

Solution:

  • remove to_lowercase() from group extraction, replace the lowercase-map lookup in sync_jwt_groups with exact try_get_role_by_name,
  • delete the now-unused roles_by_lowercase_name and try_get_role_by_name_case_insensitive methods

Testing:

  • updated three oidc.rs unit tests
  • added mzcompose workflow oidc_group_sync_case_sensitive with an OIDC mock server to verify "Admin" cannot escalate to the admin role

Remove these sections if your commit already has a good description!

Fixes: SQL-276

@mtabebe mtabebe force-pushed the ma/sso/fix-lowercase branch 3 times, most recently from af799f4 to ea0ef62 Compare May 11, 2026 17:02
Problem:
JWT group names were lowercased before catalog lookup. When two roles
differ only by case (e.g. `admin` and `"Admin"`), the lowercase map
built by `roles_by_lowercase_name` silently picked the wrong role due
to BTreeMap last-writer-wins semantics.

Solution:
- remove `to_lowercase()` from group extraction, replace the
lowercase-map lookup in `sync_jwt_groups` with exact `try_get_role_by_name`,
- delete the now-unused `roles_by_lowercase_name` and
`try_get_role_by_name_case_insensitive` methods

Testing:
- updated three oidc.rs unit tests
- added mzcompose workflow `oidc_group_sync_case_sensitive` with an OIDC
mock server to verify "Admin" cannot escalate to the `admin` role
@mtabebe mtabebe force-pushed the ma/sso/fix-lowercase branch from ea0ef62 to b334d8c Compare May 11, 2026 17:15
@mtabebe mtabebe requested a review from SangJunBak May 11, 2026 17:33
@mtabebe mtabebe marked this pull request as ready for review May 11, 2026 17:34
@mtabebe mtabebe requested a review from a team as a code owner May 11, 2026 17:34
Comment on lines +169 to +170
// Check case-insensitively so "MZ_SYSTEM" is also blocked.
if catalog::is_reserved_role_name(&group.to_lowercase()) {
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.

I wonder if we need to check this case? Thinking the "No matching Materialize Role" warning is fine

let groups: Vec<String> = raw_groups
.into_iter()
.map(|g| g.trim().to_lowercase())
.map(|g| g.trim().to_string())
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.

Should we still trim the groups? Given we're not normalizing anymore. E.g. there could exist a role " wee wwoo "

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.

2 participants