Skip to content

SetEquals/SetEqualsInt/Set2DEquals sort their arguments in place; comparing live policy rows corrupts the model and flips Enforce results #1752

Closed

Description

@lenamonj

util.SetEquals, util.SetEqualsInt and util.Set2DEquals call sort.Strings / sort.Ints / sort.Sort directly on both arguments. They are comparison helpers, so callers reasonably treat them as read-only, but any caller that passes a slice it does not own gets that slice reordered in place.

The sharpest consequence: Enforcer.GetPermissionsForUser returns the model's live policy rows. Passing its result to Set2DEquals sorts each stored rule's fields in place, so a rule like p, zoe, data1, read becomes data1, read, zoe inside the model, and a request that was allowed before the comparison is denied after it.

Reproduction against master (34297a1):

a := stringadapter.NewAdapter("p, zoe, data1, read")
e, _ := casbin.NewEnforcer(m, a)

before, _ := e.Enforce("zoe", "data1", "read")
fmt.Println("enforce before:", before)

perms, _ := e.GetPermissionsForUser("zoe")
util.Set2DEquals(perms, [][]string{{"zoe", "data1", "read"}})

policy, _ := e.GetPolicy()
fmt.Println("stored policy after comparison:", policy)
after, _ := e.Enforce("zoe", "data1", "read")
fmt.Println("enforce after:", after)

Output:

enforce before: true
stored policy after comparison: [[data1 read zoe]]
enforce after: false

The fix is small: sort copies instead of the arguments (and for Set2DEquals, copies of the inner rows as well, since sorting a row's fields is the mutation that corrupts a policy rule). I have it ready with a regression test and will open a PR referencing this issue.

Activity

  1. self-assigned this
    on Sep 9, 2026
  2. hsluoyz commented on Sep 9, 2026

    @hsluoyz
    Member

    fixed in: 071dce1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions