-
Notifications
You must be signed in to change notification settings - Fork 15
GRANT with partial member list silently destroys existing access rules #89
Description
Bug Report: GRANT with partial member list silently destroys existing access rules
mxcli version: v0.3.0 (run ./mxcli --version to confirm; local build may show dirty suffix)
Mendix version: 10.24.15.93102
Severity: High — silent security regression, no warning or error
Summary
When issuing a GRANT statement on an entity that already has access rules for the specified roles, mxcli replaces the entire existing access rule with the new partial list instead of adding to it. The operation succeeds silently — no warning, no diff, no indication that existing permissions were destroyed.
Steps to Reproduce
The following is a self-contained reproduction. Role and entity names are illustrative; the behavior is not project-specific.
Step 1 — Create entity with existing access rules:
CREATE PERSISTENT ENTITY MyModule.Product (
Name: String(200),
Price: Decimal,
IsActive: Boolean DEFAULT true
);
GRANT MyModule.Viewer ON MyModule.Product (
READ (Name, Price)
);At this point, DESCRIBE ENTITY MyModule.Product shows Viewer has READ on Name and Price.
Step 2 — Add a new attribute and grant access to it:
ALTER ENTITY MyModule.Product
ADD ATTRIBUTE Notes: String(500);
GRANT MyModule.Viewer ON MyModule.Product (READ (Notes));Expected result: Viewer gains READ on Notes in addition to the existing Name and Price.
Actual result: Viewer's entire access rule is replaced. Only Notes remains. Name and Price access is silently destroyed.
Verification:
DESCRIBE ENTITY MyModule.Product;
-- Shows: GRANT MyModule.Viewer ON MyModule.Product (READ (Notes))
-- Name and Price are goneReal-World Reproduction (Original Discovery)
This was first observed on entity Masterdata.Characteristic. The before-state (from DESCRIBE ENTITY) was:
GRANT Masterdata.Employee, Masterdata.ITAdmin, Masterdata.ITEmployee, Masterdata.ProductionManager
ON Masterdata.Characteristic (
READ (CharacteristicType, CharacteristicName, StringValue, DateTimeValue,
IntegerValue, DecimalValue, IsBooleanValue, Characteristic_Asset)
);After issuing:
GRANT Masterdata.Controller, Masterdata.FinanceOfficer
ON Masterdata.Characteristic (READ (IsActive));The roles Controller and FinanceOfficer — which previously had broader READ access — were reduced to only READ (IsActive). The security regression was not caught by mxcli lint and was only discovered during manual review in Studio Pro.
Why This Is Dangerous
- Silent failure — mxcli accepts the MDL and executes without error. Lint passes.
DESCRIBEshows the new broken state with no indication anything was removed. - Counterintuitive semantics — In SQL and virtually every other permission system,
GRANTis additive. Developers naturally expectGRANT role ON t (READ (newField))to add a privilege, not replace existing ones. - Unreachable via Studio Pro — The GUI always preserves the full permission matrix. This broken state can only be produced through mxcli, making it invisible to developers who verify in Studio Pro after the fact.
- Silent production impact — Users with affected roles lose field-level access with no runtime error. The failure only surfaces when a user tries to read a field that was silently removed.
Expected Behavior
Option A (preferred): GRANT should be additive. GRANT role ON Entity (READ (newMember)) merges newMember into the existing access rule without touching other members.
Option B (acceptable): If replace-semantics are intentional or technically required by the Mendix model, mxcli should warn before destroying existing permissions:
Warning: GRANT for role MyModule.Viewer will remove existing READ access on:
Name, Price
Use --replace to confirm, or include all members explicitly.
Workaround (until fixed)
The only safe way to add a member to existing entity access rules:
- Run
DESCRIBE ENTITY Module.Entity— capture all current GRANTs - For each affected role, reconstruct the complete GRANT including all existing members plus the new one
- Execute the full reconstructed GRANT
This is easy to forget, especially for AI-assisted or scripted workflows. A tool-level fix is strongly preferable.
Additional Context
This bug was discovered during AI-assisted Mendix development using Claude Code + mxcli. The agent issued syntactically correct targeted GRANTs based on reasonable assumptions about additive semantics, and the security regression was only caught during manual Studio Pro review.
We have also observed other operations where MDL is silently accepted but produces unexpected internal BSON state (list variable type serialization, association member linking). We will file those separately as they may warrant independent investigation.