Skip to content

Quoted policy conditions with commas: load works, exact batch delete does not remove all rules #1733

Description

@Ravichandran-T-S

Summary

We use Casbin with 6-field p policies where the last field is a condition expression (quoted in CSV). Policies load correctly, but on exact batch delete (RemovePolicies) not all matching rules are removed — we see partial deletes when the condition text contains commas.

Environment

  • github.com/casbin/casbin/v2 v2.77.x
  • Large policy set (~350k p rules)
  • Incremental deletes via RemovePolicies with full 6-field rules (including condition)

What we see

  • Delete event: 14 policies (user, tenant, resource, access, role, condition)
  • Requested: batch delete of 14 exact-match rules
  • Result: only 9 removed from persisted policy data
  • The 5 not removed all have commas inside the condition string
  • Rules with conditions that have no commas (e.g. only && between matchers) delete as expected

When commas appear in conditions (valid ABAC expressions)

Commas are not only in in (...) lists. They can also appear in other matchers, for example:

  • List / enum checks:
    r.attrs.ExceptionAllowed in ('( true','false )')
  • Comma-separated allowed values in a matcher:
    r.attrs.Center =~ '^center1,center2,center3$'
    or similar patterns where the regex/value side lists multiple centers/streams
  • Multiple constraints in one expression:
    (r.attrs.Center =~ '^.*$' && r.attrs.Stream =~ '^.*$' && ...)

So the condition field is a free-form expression, not a simple scalar — CSV must treat the whole quoted field as one token, including any commas inside it.

Example — removed successfully (no commas in condition)

csv p, aqDsp4Rqe0PqHDJMZDI4P, aUSsW8GI03dyQ0AIFVn92, RESOURCE_STUDENT_MANAGEMENT, ACCESS_LEVEL_FULL, e0bmnxKv9L5AQGUwBtHFN, "(r.attrs.Center =~ '^.*$' && r.attrs.Stream =~ '^.*$')"

Example - Policies we have trouble removing (commas inside quoted condition)


p, aqDsp4Rqe0PqHDJMZDI4P, aUSsW8GI03dyQ0AIFVn92, RESOURCE_SUPPORT_ID_CARD, ACCESS_LEVEL_FULL, e0bmnxKv9L5AQGUwBtHFN, "(r.attrs.Center =~ '^.*$' && r.attrs.Stream =~ '^.*$' && r.attrs.CourseType =~ '^.*$' && r.attrs.ExceptionAllowed in ('( true','false )') && r.attrs.DiscountPercent < 100)"

p, aqDsp4Rqe0PqHDJMZDI4P, aUSsW8GI03dyQ0AIFVn92, RESOURCE_SUPPORT_STREAM_CHANGE, ACCESS_LEVEL_FULL, e0bmnxKv9L5AQGUwBtHFN, "(r.attrs.ExceptionAllowed in ('( true','false )') && r.attrs.DiscountPercent < 100 && r.attrs.Center =~ '^.*$' && r.attrs.Stream =~ '^.*$' && r.attrs.CourseType =~ '^.*$')"

p, aqDsp4Rqe0PqHDJMZDI4P, aUSsW8GI03dyQ0AIFVn92, RESOURCE_SUPPORT_BATCH_CHANGE, ACCESS_LEVEL_FULL, e0bmnxKv9L5AQGUwBtHFN, "(r.attrs.Center =~ '^.*$' && r.attrs.Stream =~ '^.*$' && r.attrs.CourseType =~ '^.*$' && r.attrs.ExceptionAllowed in ('( true','false )') && r.attrs.DiscountPercent < 100)"

p, aqDsp4Rqe0PqHDJMZDI4P, aUSsW8GI03dyQ0AIFVn92, RESOURCE_SUPPORT_PII_DATA, ACCESS_LEVEL_READ, e0bmnxKv9L5AQGUwBtHFN, "(r.attrs.Center =~ '^.*$' && r.attrs.Stream =~ '^.*$' && r.attrs.CourseType =~ '^.*$' && r.attrs.ExceptionAllowed in ('( true','false )'))"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions