mirror of
https://github.com/zitadel/zitadel.git
synced 2026-07-25 18:28:00 +00:00
* Use slices.Contains over custom function * Correctly remove roles from granted roles * fix(setup): repair user grants with stale roles (GHSA-v859-c572-qh5p) Add setup step 73 that reconciles existing user grants whose roles were left too broad by the buggy cascade removal in removeRoleFromUserGrant. The corruption lives in the eventstore event payloads, so the step pushes a corrective user.grant.cascade.changed event per affected grant (roles intersected with the currently valid set) and re-triggers the user grant projection. Runs in the second setup slice, after the projection tables it reads have been created. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(setup): scope GHSA-v859-c572-qh5p repair to grant-based user grants Direct user grants can never be hit by this bug (only ChangeProjectGrant's multi-role cascade to grant-based grants can trigger it), so drop the direct-grant branch from the finder query to avoid stripping unrelated, legitimate roles that merely mismatch for other reasons (e.g. stale role_key drift). Also exclude removed instances from the migration scope, and log the number of grants fixed per instance. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Livio Spring <9405495+livio-a@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
40 lines
2.0 KiB
SQL
40 lines
2.0 KiB
SQL
-- Finds user grants whose stored roles include roles that are no longer valid
|
|
-- (the residue left by the buggy cascade removal, GHSA-v859-c572-qh5p), and
|
|
-- returns the corrected role set for each. $1 = instance_id, run once per instance.
|
|
--
|
|
-- Scope: only grant-based user grants (ug.grant_id set) can be affected by this
|
|
-- bug. It was introduced by ChangeProjectGrant (internal/command/project_grant.go),
|
|
-- which cascades a *multi*-role removal to the user grants tied to that project
|
|
-- grant. Direct user grants never go through a multi-role removal call, so any
|
|
-- role mismatch there is unrelated to this CVE (e.g. pre-existing role_key drift)
|
|
-- and must not be "fixed" here to avoid stripping unrelated, legitimate roles.
|
|
WITH computed AS (
|
|
SELECT
|
|
ug.id,
|
|
ug.resource_owner,
|
|
ug.roles AS current_roles,
|
|
-- Recompute the roles this grant is actually allowed to keep by filtering
|
|
-- its current roles down to the ones still granted by the project grant.
|
|
COALESCE(
|
|
ARRAY(
|
|
SELECT r
|
|
FROM unnest(ug.roles) AS r -- expand the stored roles array
|
|
WHERE r = ANY(pg.granted_role_keys)
|
|
),
|
|
ARRAY[]::TEXT[] -- keep NULL out; use empty array
|
|
) AS valid_roles
|
|
FROM projections.user_grants5 ug
|
|
JOIN projections.project_grants4 pg
|
|
ON pg.instance_id = ug.instance_id
|
|
AND pg.grant_id = ug.grant_id
|
|
WHERE ug.instance_id = $1
|
|
AND ug.grant_id IS NOT NULL AND ug.grant_id <> '' -- direct grants are out of scope, see above
|
|
AND ug.roles IS NOT NULL
|
|
AND cardinality(ug.roles) > 0 -- nothing to correct on empty grants
|
|
)
|
|
-- valid_roles is always a subset of current_roles, so a size mismatch means at
|
|
-- least one stale role was dropped -> this grant needs a corrective event.
|
|
SELECT id, resource_owner, valid_roles
|
|
FROM computed
|
|
WHERE cardinality(valid_roles) <> cardinality(current_roles);
|