Skip to content

GRANT ... WHERE overwrites instead of merging the attribute list (silent security regression) #936

Description

@WouterHooglandTOF

mxcli bug: GRANT ... ON ENTITY ... WHERE '...' overwrites instead of merging the attribute list

mxcli version

nightly-20260720-88077af1 (2026-07-20T06:06:00Z)

Mendix version

10.24.20.105674

Severity

High. This is a silent security regression: re-granting additional attributes to a role/entity/XPath combination that already has an access rule replaces that rule's attribute list instead of adding to it, with no error, warning, or diff shown. manage-security.md documents GRANT as "additive — it merges with existing access, never removes permissions," which is true when no WHERE clause is involved, but is false once a WHERE (XPath) clause matches an existing rule: read/write access to every attribute not mentioned in the new GRANT statement is silently revoked for that role on that XPath-scoped rule. A developer following the documented "additive" behavior to extend an existing rule with one or two new attributes will, without any indication, strip access to every other attribute already granted under that rule.

Steps to reproduce (project-independent)

Minimal domain model + existing XPath-scoped grant:

create persistent entity Sample.Order (
  Number: string(50),
  Status: string(50),
  Total: decimal
);
/
create module role Sample.Viewer;
/
grant Sample.Viewer on Sample.Order (read (Number, Status, Total)) where '[Status != '''']';

Verify: describe entity Sample.Order shows the rule with all 3 attributes readable for Sample.Viewer under that XPath.

Now add one more attribute to the entity and grant read on it, using the same role and the same XPath text (the documented "additive" pattern):

alter entity Sample.Order add attribute Priority: integer;
/
grant Sample.Viewer on Sample.Order (read (Priority)) where '[Status != '''']';

mxcli exec reports success with no error or warning.

Then re-run describe entity Sample.Order.

Expected behaviour

Per the documented additive semantics, the rule should now read (Number, Status, Total, Priority) — the new attribute merged into the existing rule (same role + same XPath).

Actual behaviour (verbatim from my session, generalized names)

The rule's attribute list is replaced, not merged. In my session (real entity/attribute names, same mechanism):

  • Before, an existing rule read:
    grant Module.RoleA, Module.RoleB on Module.Entity (read (AttrX, AttrY, AttrZ, AttrRangorde, AttrDate, Assoc1, Assoc2)) where '[XPathCondition1][XPathCondition2]';
    
  • I ran a grant for the same Module.RoleA, Module.RoleB / Module.Entity / identical where string, adding 3 new attributes:
    grant Module.RoleA, Module.RoleB on Module.Entity (read (NewAttr1, NewAttr2, NewAttr3)) where '[XPathCondition1][XPathCondition2]';
    
  • mxcli exec printed:
    Granted access on Module.Entity to Module.RoleA, Module.RoleB
      Result: read (NewAttr1, NewAttr2, NewAttr3)
    
    (no error, no warning that anything else changed)
  • A subsequent describe entity Module.Entity showed the rule now reading only (NewAttr1, NewAttr2, NewAttr3)AttrX, AttrY, AttrZ, AttrRangorde, AttrDate, Assoc1, Assoc2 were gone from that rule (i.e. read access to all 7 original attributes/associations was silently revoked for RoleA/RoleB under that XPath). This happened identically on two separate rules (two different role-pairs, two different attribute sets, same entity) in the same session — not a one-off fluke.
  • This is distinct from GRANT calls without a WHERE clause, which did behave additively in the same session (merging a new attribute into a role's unconstrained grant on a different entity worked as documented).

I only discovered the regression because I re-ran describe entity immediately afterward as a sanity check (per this workspace's coding.md rule to verify after every model change) — nothing in mxcli's own grant output flagged it.

Workaround

Applied in-session: before granting additional attributes on a rule that has a WHERE clause, first describe entity to capture the existing full attribute list for that exact role+entity+XPath combination, then issue one GRANT that includes the union of the old and new attributes (plus the identical WHERE text) — i.e. always treat GRANT ... WHERE as "set/replace this rule's attribute list," not "add to it," and manually pre-merge. After doing this, describe entity confirmed the rule correctly contained the full original + new attribute list.

Diagnostic bundle

Available: yes — mxcli-diag-20260819-220247.tar.gz (workspace root). Note: the bundle does not log a before/after diff of the affected rules' attribute lists (the grant log lines only show the Result: summary quoted above, which itself is what's misleading — it doesn't reflect the full post-grant attribute list either) — the verbatim before/after describe entity output above was captured directly from the terminal during the session and is not otherwise present in the bundle.

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